]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
QemuServer: remove PCI sysfs helpers
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
990fc5e2 4use warnings;
1e3baf05
DM
5use POSIX;
6use IO::Handle;
7use IO::Select;
8use IO::File;
9use IO::Dir;
10use IO::Socket::UNIX;
11use File::Basename;
12use File::Path;
13use File::stat;
14use Getopt::Long;
fc1ddcdc 15use Digest::SHA;
1e3baf05
DM
16use Fcntl ':flock';
17use Cwd 'abs_path';
18use IPC::Open3;
c971c4f2 19use JSON;
1e3baf05
DM
20use Fcntl;
21use PVE::SafeSyslog;
22use Storable qw(dclone);
23use PVE::Exception qw(raise raise_param_exc);
24use PVE::Storage;
0c9a7596 25use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach $IPV6RE);
b7ba6b79 26use PVE::JSONSchema qw(get_standard_option);
1e3baf05
DM
27use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
28use PVE::INotify;
29use PVE::ProcFSTools;
ffda963f 30use PVE::QemuConfig;
26f11676 31use PVE::QMPClient;
91bd6c90 32use PVE::RPCEnvironment;
de9768f0 33use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr);
3f669af2 34use PVE::QemuServer::Memory;
d40e5e18 35use PVE::QemuServer::USB qw(parse_usb_device);
0c9a7596 36use PVE::QemuServer::Cloudinit;
b71351a7 37use PVE::SysFSTools;
d04d6af1 38use PVE::Systemd;
6b64503e 39use Time::HiRes qw(gettimeofday);
a783c78e 40use File::Copy qw(copy);
46630a5f 41use URI::Escape;
1e3baf05 42
102cf9d8 43my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/';
96ed3574
WB
44my $OVMF = {
45 x86_64 => [
46 "$EDK2_FW_BASE/OVMF_CODE.fd",
47 "$EDK2_FW_BASE/OVMF_VARS.fd"
48 ],
49 aarch64 => [
50 "$EDK2_FW_BASE/AAVMF_CODE.fd",
51 "$EDK2_FW_BASE/AAVMF_VARS.fd"
52 ],
53};
2ddc0a5c 54
e5eaa028
WL
55my $qemu_snap_storage = {rbd => 1, sheepdog => 1};
56
7f0b5beb 57my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 58
9c52f5ed
WB
59my $QEMU_FORMAT_RE = qr/raw|cow|qcow|qcow2|qed|vmdk|cloop/;
60
19672434 61# Note about locking: we use flock on the config file protect
1e3baf05
DM
62# against concurent actions.
63# Aditionaly, we have a 'lock' setting in the config file. This
22c377f0 64# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
1e3baf05
DM
65# allowed when such lock is set. But you can ignore this kind of
66# lock with the --skiplock flag.
67
97d62eb7 68cfs_register_file('/qemu-server/',
1858638f
DM
69 \&parse_vm_config,
70 \&write_vm_config);
1e3baf05 71
3ea94c60
DM
72PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
73 description => "Some command save/restore state from this location.",
74 type => 'string',
75 maxLength => 128,
76 optional => 1,
77});
78
8abd398b
DM
79PVE::JSONSchema::register_standard_option('pve-snapshot-name', {
80 description => "The name of the snapshot.",
81 type => 'string', format => 'pve-configid',
82 maxLength => 40,
83});
84
c7d2b650
DM
85PVE::JSONSchema::register_standard_option('pve-qm-image-format', {
86 type => 'string',
87 enum => [qw(raw cow qcow qed qcow2 vmdk cloop)],
88 description => "The drive's backing file's data format.",
89 optional => 1,
90});
91
c6737ef1
DC
92PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
93 description => "Specifies the Qemu machine type.",
94 type => 'string',
d731ecbe 95 pattern => '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?|virt(?:-\d+\.\d+)?)',
c6737ef1
DC
96 maxLength => 40,
97 optional => 1,
98});
99
1e3baf05
DM
100#no warnings 'redefine';
101
c8effec3
AD
102sub cgroups_write {
103 my ($controller, $vmid, $option, $value) = @_;
104
3a515a88
DM
105 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
106 PVE::ProcFSTools::write_proc_entry($path, $value);
c8effec3
AD
107
108}
109
1e3baf05
DM
110my $nodename = PVE::INotify::nodename();
111
112mkdir "/etc/pve/nodes/$nodename";
113my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
114mkdir $confdir;
115
116my $var_run_tmpdir = "/var/run/qemu-server";
117mkdir $var_run_tmpdir;
118
119my $lock_dir = "/var/lock/qemu-server";
120mkdir $lock_dir;
121
122my $pcisysfs = "/sys/bus/pci";
123
8930da74
DM
124my $cpu_vendor_list = {
125 # Intel CPUs
126 486 => 'GenuineIntel',
127 pentium => 'GenuineIntel',
128 pentium2 => 'GenuineIntel',
129 pentium3 => 'GenuineIntel',
130 coreduo => 'GenuineIntel',
131 core2duo => 'GenuineIntel',
132 Conroe => 'GenuineIntel',
9052caba 133 Penryn => 'GenuineIntel',
8930da74 134 Nehalem => 'GenuineIntel',
9052caba 135 'Nehalem-IBRS' => 'GenuineIntel',
8930da74 136 Westmere => 'GenuineIntel',
9052caba 137 'Westmere-IBRS' => 'GenuineIntel',
8930da74 138 SandyBridge => 'GenuineIntel',
9052caba 139 'SandyBridge-IBRS' => 'GenuineIntel',
8930da74 140 IvyBridge => 'GenuineIntel',
9052caba 141 'IvyBridge-IBRS' => 'GenuineIntel',
8930da74 142 Haswell => 'GenuineIntel',
9052caba 143 'Haswell-IBRS' => 'GenuineIntel',
8930da74 144 'Haswell-noTSX' => 'GenuineIntel',
9052caba 145 'Haswell-noTSX-IBRS' => 'GenuineIntel',
8930da74 146 Broadwell => 'GenuineIntel',
9052caba 147 'Broadwell-IBRS' => 'GenuineIntel',
8930da74 148 'Broadwell-noTSX' => 'GenuineIntel',
9052caba 149 'Broadwell-noTSX-IBRS' => 'GenuineIntel',
3db920fc 150 'Skylake-Client' => 'GenuineIntel',
9052caba 151 'Skylake-Client-IBRS' => 'GenuineIntel',
a446dbf4
FG
152 'Skylake-Server' => 'GenuineIntel',
153 'Skylake-Server-IBRS' => 'GenuineIntel',
9052caba 154
8930da74
DM
155 # AMD CPUs
156 athlon => 'AuthenticAMD',
157 phenom => 'AuthenticAMD',
158 Opteron_G1 => 'AuthenticAMD',
159 Opteron_G2 => 'AuthenticAMD',
160 Opteron_G3 => 'AuthenticAMD',
161 Opteron_G4 => 'AuthenticAMD',
162 Opteron_G5 => 'AuthenticAMD',
2a850ee8
WB
163 EPYC => 'AuthenticAMD',
164 'EPYC-IBPB' => 'AuthenticAMD',
8930da74
DM
165
166 # generic types, use vendor from host node
167 host => 'default',
168 kvm32 => 'default',
169 kvm64 => 'default',
170 qemu32 => 'default',
171 qemu64 => 'default',
a446dbf4 172 max => 'default',
8930da74
DM
173};
174
eabc189e 175my $cpu_flag = qr/[+-](pcid|spec-ctrl|ibpb|ssbd|virt-ssbd|amd-ssbd|amd-no-ssb|pdpe1gb)/;
049fc9eb 176
ff6ffe20 177my $cpu_fmt = {
16a91d65
WB
178 cputype => {
179 description => "Emulated CPU type.",
180 type => 'string',
7f694a71 181 enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
16a91d65
WB
182 default => 'kvm64',
183 default_key => 1,
184 },
185 hidden => {
186 description => "Do not identify as a KVM virtual machine.",
187 type => 'boolean',
188 optional => 1,
189 default => 0
190 },
39fd79e2 191 flags => {
049fc9eb
FG
192 description => "List of additional CPU flags separated by ';'."
193 . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
eabc189e 194 . " Currently supported flags: 'pcid', 'spec-ctrl', 'ibpb', 'ssbd', 'virt-ssbd', 'amd-ssbd', 'amd-no-ssb', 'pdpe1gb'.",
049fc9eb 195 format_description => '+FLAG[;-FLAG...]',
39fd79e2 196 type => 'string',
049fc9eb 197 pattern => qr/$cpu_flag(;$cpu_flag)*/,
39fd79e2 198 optional => 1,
39fd79e2 199 },
16a91d65
WB
200};
201
ec3582b5
WB
202my $watchdog_fmt = {
203 model => {
204 default_key => 1,
205 type => 'string',
206 enum => [qw(i6300esb ib700)],
207 description => "Watchdog type to emulate.",
208 default => 'i6300esb',
209 optional => 1,
210 },
211 action => {
212 type => 'string',
213 enum => [qw(reset shutdown poweroff pause debug none)],
214 description => "The action to perform if after activation the guest fails to poll the watchdog in time.",
215 optional => 1,
216 },
217};
218PVE::JSONSchema::register_format('pve-qm-watchdog', $watchdog_fmt);
219
9d66b397
SI
220my $agent_fmt = {
221 enabled => {
222 description => "Enable/disable Qemu GuestAgent.",
223 type => 'boolean',
224 default => 0,
225 default_key => 1,
226 },
227 fstrim_cloned_disks => {
228 description => "Run fstrim after cloning/moving a disk.",
229 type => 'boolean',
230 optional => 1,
231 default => 0
232 },
233};
234
55655ebc
DC
235my $vga_fmt = {
236 type => {
237 description => "Select the VGA type.",
238 type => 'string',
239 default => 'std',
240 optional => 1,
241 default_key => 1,
242 enum => [qw(cirrus qxl qxl2 qxl3 qxl4 serial0 serial1 serial2 serial3 std virtio vmware)],
243 },
244 memory => {
245 description => "Sets the VGA memory (in MiB). Has no effect with serial display.",
246 type => 'integer',
247 optional => 1,
248 minimum => 4,
249 maximum => 512,
250 },
251};
252
1e3baf05
DM
253my $confdesc = {
254 onboot => {
255 optional => 1,
256 type => 'boolean',
257 description => "Specifies whether a VM will be started during system bootup.",
258 default => 0,
259 },
260 autostart => {
261 optional => 1,
262 type => 'boolean',
263 description => "Automatic restart after crash (currently ignored).",
264 default => 0,
265 },
2ff09f52
DA
266 hotplug => {
267 optional => 1,
b3c2bdd1
DM
268 type => 'string', format => 'pve-hotplug-features',
269 description => "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
270 default => 'network,disk,usb',
2ff09f52 271 },
1e3baf05
DM
272 reboot => {
273 optional => 1,
274 type => 'boolean',
275 description => "Allow reboot. If set to '0' the VM exit on reboot.",
276 default => 1,
277 },
278 lock => {
279 optional => 1,
280 type => 'string',
281 description => "Lock/unlock the VM.",
22c377f0 282 enum => [qw(migrate backup snapshot rollback)],
1e3baf05
DM
283 },
284 cpulimit => {
285 optional => 1,
c6f773b8 286 type => 'number',
52261945
DM
287 description => "Limit of CPU usage.",
288 verbose_description => "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
1e3baf05 289 minimum => 0,
c6f773b8 290 maximum => 128,
52261945 291 default => 0,
1e3baf05
DM
292 },
293 cpuunits => {
294 optional => 1,
295 type => 'integer',
52261945 296 description => "CPU weight for a VM.",
237239bf
PA
297 verbose_description => "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.",
298 minimum => 2,
299 maximum => 262144,
613d76a1 300 default => 1024,
1e3baf05
DM
301 },
302 memory => {
303 optional => 1,
304 type => 'integer',
7878afeb 305 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
306 minimum => 16,
307 default => 512,
308 },
13a48620
DA
309 balloon => {
310 optional => 1,
311 type => 'integer',
8b1accf7
DM
312 description => "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
313 minimum => 0,
314 },
315 shares => {
316 optional => 1,
317 type => 'integer',
82329cd5 318 description => "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning. Auto-ballooning is done by pvestatd.",
8b1accf7
DM
319 minimum => 0,
320 maximum => 50000,
321 default => 1000,
13a48620 322 },
1e3baf05
DM
323 keyboard => {
324 optional => 1,
325 type => 'string',
f889aa0f 326 description => "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.cfg' configuration file.".
aea47dd6 327 "It should not be necessary to set it.",
e95fe75f 328 enum => PVE::Tools::kvmkeymaplist(),
aea47dd6 329 default => undef,
1e3baf05
DM
330 },
331 name => {
332 optional => 1,
7fabe17d 333 type => 'string', format => 'dns-name',
1e3baf05
DM
334 description => "Set a name for the VM. Only used on the configuration web interface.",
335 },
cdd20088
AD
336 scsihw => {
337 optional => 1,
338 type => 'string',
52261945 339 description => "SCSI controller model",
6731a4cf 340 enum => [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
cdd20088
AD
341 default => 'lsi',
342 },
1e3baf05
DM
343 description => {
344 optional => 1,
345 type => 'string',
0581fe4f 346 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
347 },
348 ostype => {
349 optional => 1,
350 type => 'string',
0cb9971e 351 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
52261945
DM
352 description => "Specify guest operating system.",
353 verbose_description => <<EODESC,
354Specify guest operating system. This is used to enable special
355optimization/features for specific operating systems:
356
357[horizontal]
358other;; unspecified OS
359wxp;; Microsoft Windows XP
360w2k;; Microsoft Windows 2000
361w2k3;; Microsoft Windows 2003
362w2k8;; Microsoft Windows 2008
363wvista;; Microsoft Windows Vista
364win7;; Microsoft Windows 7
44c2a647
TL
365win8;; Microsoft Windows 8/2012/2012r2
366win10;; Microsoft Windows 10/2016
52261945
DM
367l24;; Linux 2.4 Kernel
368l26;; Linux 2.6/3.X Kernel
369solaris;; Solaris/OpenSolaris/OpenIndiania kernel
1e3baf05
DM
370EODESC
371 },
372 boot => {
373 optional => 1,
374 type => 'string',
375 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
376 pattern => '[acdn]{1,4}',
32baffb4 377 default => 'cdn',
1e3baf05
DM
378 },
379 bootdisk => {
380 optional => 1,
381 type => 'string', format => 'pve-qm-bootdisk',
382 description => "Enable booting from specified disk.",
03e480fc 383 pattern => '(ide|sata|scsi|virtio)\d+',
1e3baf05
DM
384 },
385 smp => {
386 optional => 1,
387 type => 'integer',
388 description => "The number of CPUs. Please use option -sockets instead.",
389 minimum => 1,
390 default => 1,
391 },
392 sockets => {
393 optional => 1,
394 type => 'integer',
395 description => "The number of CPU sockets.",
396 minimum => 1,
397 default => 1,
398 },
399 cores => {
400 optional => 1,
401 type => 'integer',
402 description => "The number of cores per socket.",
403 minimum => 1,
404 default => 1,
405 },
8a010eae
AD
406 numa => {
407 optional => 1,
408 type => 'boolean',
1917695c 409 description => "Enable/disable NUMA.",
8a010eae
AD
410 default => 0,
411 },
7023f3ea
AD
412 hugepages => {
413 optional => 1,
414 type => 'string',
415 description => "Enable/disable hugepages memory.",
416 enum => [qw(any 2 1024)],
417 },
de9d1e55 418 vcpus => {
3bd18e48
AD
419 optional => 1,
420 type => 'integer',
de9d1e55 421 description => "Number of hotplugged vcpus.",
3bd18e48 422 minimum => 1,
de9d1e55 423 default => 0,
3bd18e48 424 },
1e3baf05
DM
425 acpi => {
426 optional => 1,
427 type => 'boolean',
428 description => "Enable/disable ACPI.",
429 default => 1,
430 },
bc84dcca 431 agent => {
ab6a046f 432 optional => 1,
9d66b397
SI
433 description => "Enable/disable Qemu GuestAgent and its properties.",
434 type => 'string',
435 format => $agent_fmt,
ab6a046f 436 },
1e3baf05
DM
437 kvm => {
438 optional => 1,
439 type => 'boolean',
440 description => "Enable/disable KVM hardware virtualization.",
441 default => 1,
442 },
443 tdf => {
444 optional => 1,
445 type => 'boolean',
8c559505
DM
446 description => "Enable/disable time drift fix.",
447 default => 0,
1e3baf05 448 },
19672434 449 localtime => {
1e3baf05
DM
450 optional => 1,
451 type => 'boolean',
452 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
453 },
454 freeze => {
455 optional => 1,
456 type => 'boolean',
457 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
458 },
459 vga => {
460 optional => 1,
55655ebc
DC
461 type => 'string', format => $vga_fmt,
462 description => "Configure the VGA hardware.",
463 verbose_description => "Configure the VGA Hardware. If you want to use ".
464 "high resolution modes (>= 1280x1024x16) you may need to increase " .
465 "the vga memory option. Since QEMU 2.9 the default VGA display type " .
466 "is 'std' for all OS types besides some Windows versions (XP and " .
467 "older) which use 'cirrus'. The 'qxl' option enables the SPICE " .
468 "display server. For win* OS you can select how many independent " .
469 "displays you want, Linux guests can add displays them self.\n".
470 "You can also run without any graphic card, using a serial device as terminal.",
1e3baf05 471 },
0ea9541d
DM
472 watchdog => {
473 optional => 1,
474 type => 'string', format => 'pve-qm-watchdog',
52261945
DM
475 description => "Create a virtual hardware watchdog device.",
476 verbose_description => "Create a virtual hardware watchdog device. Once enabled" .
1917695c
TL
477 " (by a guest action), the watchdog must be periodically polled " .
478 "by an agent inside the guest or else the watchdog will reset " .
479 "the guest (or execute the respective action specified)",
0ea9541d 480 },
1e3baf05
DM
481 startdate => {
482 optional => 1,
19672434 483 type => 'string',
1e3baf05
DM
484 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
485 description => "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
486 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
487 default => 'now',
488 },
43574f73 489 startup => get_standard_option('pve-startup-order'),
68eda3ab
AD
490 template => {
491 optional => 1,
492 type => 'boolean',
493 description => "Enable/disable Template.",
494 default => 0,
495 },
1e3baf05
DM
496 args => {
497 optional => 1,
498 type => 'string',
52261945
DM
499 description => "Arbitrary arguments passed to kvm.",
500 verbose_description => <<EODESCR,
c7a8aad6 501Arbitrary arguments passed to kvm, for example:
1e3baf05
DM
502
503args: -no-reboot -no-hpet
c7a8aad6
FG
504
505NOTE: this option is for experts only.
1e3baf05
DM
506EODESCR
507 },
508 tablet => {
509 optional => 1,
510 type => 'boolean',
511 default => 1,
52261945
DM
512 description => "Enable/disable the USB tablet device.",
513 verbose_description => "Enable/disable the USB tablet device. This device is " .
1917695c
TL
514 "usually needed to allow absolute mouse positioning with VNC. " .
515 "Else the mouse runs out of sync with normal VNC clients. " .
516 "If you're running lots of console-only guests on one host, " .
517 "you may consider disabling this to save some context switches. " .
518 "This is turned off by default if you use spice (-vga=qxl).",
1e3baf05
DM
519 },
520 migrate_speed => {
521 optional => 1,
522 type => 'integer',
523 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
524 minimum => 0,
525 default => 0,
526 },
527 migrate_downtime => {
528 optional => 1,
04432191 529 type => 'number',
1e3baf05
DM
530 description => "Set maximum tolerated downtime (in seconds) for migrations.",
531 minimum => 0,
04432191 532 default => 0.1,
1e3baf05
DM
533 },
534 cdrom => {
535 optional => 1,
b799312f 536 type => 'string', format => 'pve-qm-ide',
8485b9ba 537 typetext => '<volume>',
1e3baf05
DM
538 description => "This is an alias for option -ide2",
539 },
540 cpu => {
541 optional => 1,
542 description => "Emulated CPU type.",
543 type => 'string',
ff6ffe20 544 format => $cpu_fmt,
1e3baf05 545 },
b7ba6b79
DM
546 parent => get_standard_option('pve-snapshot-name', {
547 optional => 1,
548 description => "Parent snapshot name. This is used internally, and should not be modified.",
549 }),
982c7f12
DM
550 snaptime => {
551 optional => 1,
552 description => "Timestamp for snapshots.",
553 type => 'integer',
554 minimum => 0,
555 },
18bfb361
DM
556 vmstate => {
557 optional => 1,
558 type => 'string', format => 'pve-volume-id',
559 description => "Reference to a volume which stores the VM state. This is used internally for snapshots.",
560 },
253624c7
FG
561 vmstatestorage => get_standard_option('pve-storage-id', {
562 description => "Default storage for VM state volumes/files.",
563 optional => 1,
564 }),
c6737ef1
DC
565 runningmachine => get_standard_option('pve-qemu-machine', {
566 description => "Specifies the Qemu machine type of the running vm. This is used internally for snapshots.",
567 }),
568 machine => get_standard_option('pve-qemu-machine'),
d731ecbe
WB
569 arch => {
570 description => "Virtual processor architecture. Defaults to the host.",
571 optional => 1,
572 type => 'string',
573 enum => [qw(x86_64 aarch64)],
574 },
2796e7d5
DM
575 smbios1 => {
576 description => "Specify SMBIOS type 1 fields.",
577 type => 'string', format => 'pve-qm-smbios1',
2796e7d5
DM
578 maxLength => 256,
579 optional => 1,
580 },
cb0e4540
AG
581 protection => {
582 optional => 1,
583 type => 'boolean',
52261945 584 description => "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
cb0e4540
AG
585 default => 0,
586 },
3edb45e7 587 bios => {
a783c78e 588 optional => 1,
3edb45e7
DM
589 type => 'string',
590 enum => [ qw(seabios ovmf) ],
591 description => "Select BIOS implementation.",
592 default => 'seabios',
a783c78e 593 },
6ee499ff
DC
594 vmgenid => {
595 type => 'string',
596 pattern => '(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])',
597 format_description => 'UUID',
f7ed64e7
TL
598 description => "Set VM Generation ID. Use '1' to autogenerate on create or update, pass '0' to disable explicitly.",
599 verbose_description => "The VM generation ID (vmgenid) device exposes a".
600 " 128-bit integer value identifier to the guest OS. This allows to".
601 " notify the guest operating system when the virtual machine is".
602 " executed with a different configuration (e.g. snapshot execution".
603 " or creation from a template). The guest operating system notices".
604 " the change, and is then able to react as appropriate by marking".
605 " its copies of distributed databases as dirty, re-initializing its".
606 " random number generator, etc.\n".
607 "Note that auto-creation only works when done throug API/CLI create".
608 " or update methods, but not when manually editing the config file.",
609 default => "1 (autogenerated)",
6ee499ff
DC
610 optional => 1,
611 },
9ed7a77c
WB
612};
613
614my $confdesc_cloudinit = {
41cd94a0
WB
615 citype => {
616 optional => 1,
617 type => 'string',
498cdc36 618 description => 'Specifies the cloud-init configuration format. The default depends on the configured operating system type (`ostype`. We use the `nocloud` format for Linux, and `configdrive2` for windows.',
41cd94a0
WB
619 enum => ['configdrive2', 'nocloud'],
620 },
7b42f951
WB
621 ciuser => {
622 optional => 1,
623 type => 'string',
624 description => "cloud-init: User name to change ssh keys and password for instead of the image's configured default user.",
625 },
626 cipassword => {
627 optional => 1,
628 type => 'string',
1d1c4e1c 629 description => 'cloud-init: Password to assign the user. Using this is generally not recommended. Use ssh keys instead. Also note that older cloud-init versions do not support hashed passwords.',
7b42f951 630 },
0c9a7596
AD
631 searchdomain => {
632 optional => 1,
633 type => 'string',
634 description => "cloud-init: Sets DNS search domains for a container. Create will automatically use the setting from the host if neither searchdomain nor nameserver are set.",
635 },
636 nameserver => {
637 optional => 1,
638 type => 'string', format => 'address-list',
639 description => "cloud-init: Sets DNS server IP address for a container. Create will automatically use the setting from the host if neither searchdomain nor nameserver are set.",
640 },
641 sshkeys => {
642 optional => 1,
643 type => 'string',
644 format => 'urlencoded',
1d1c4e1c 645 description => "cloud-init: Setup public SSH keys (one key per line, OpenSSH format).",
0c9a7596 646 },
1e3baf05
DM
647};
648
649# what about other qemu settings ?
650#cpu => 'string',
651#machine => 'string',
652#fda => 'file',
653#fdb => 'file',
654#mtdblock => 'file',
655#sd => 'file',
656#pflash => 'file',
657#snapshot => 'bool',
658#bootp => 'file',
659##tftp => 'dir',
660##smb => 'dir',
661#kernel => 'file',
662#append => 'string',
663#initrd => 'file',
664##soundhw => 'string',
665
666while (my ($k, $v) = each %$confdesc) {
667 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
668}
669
670my $MAX_IDE_DISKS = 4;
f62db2a4 671my $MAX_SCSI_DISKS = 14;
a2650619 672my $MAX_VIRTIO_DISKS = 16;
cdb0931f 673my $MAX_SATA_DISKS = 6;
1e3baf05 674my $MAX_USB_DEVICES = 5;
5bdcf937 675my $MAX_NETS = 32;
c9db2240 676my $MAX_UNUSED_DISKS = 256;
5cffb2d2 677my $MAX_HOSTPCI_DEVICES = 4;
bae179aa 678my $MAX_SERIAL_PORTS = 4;
1989a89c 679my $MAX_PARALLEL_PORTS = 3;
2ed5d572
AD
680my $MAX_NUMA = 8;
681
ffc0d8c7
WB
682my $numa_fmt = {
683 cpus => {
684 type => "string",
685 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
52261945 686 description => "CPUs accessing this NUMA node.",
ffc0d8c7
WB
687 format_description => "id[-id];...",
688 },
689 memory => {
690 type => "number",
52261945 691 description => "Amount of memory this NUMA node provides.",
ffc0d8c7
WB
692 optional => 1,
693 },
694 hostnodes => {
695 type => "string",
696 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
52261945 697 description => "Host NUMA nodes to use.",
ffc0d8c7
WB
698 format_description => "id[-id];...",
699 optional => 1,
700 },
701 policy => {
702 type => 'string',
703 enum => [qw(preferred bind interleave)],
52261945 704 description => "NUMA allocation policy.",
ffc0d8c7
WB
705 optional => 1,
706 },
707};
708PVE::JSONSchema::register_format('pve-qm-numanode', $numa_fmt);
2ed5d572
AD
709my $numadesc = {
710 optional => 1,
ffc0d8c7 711 type => 'string', format => $numa_fmt,
52261945 712 description => "NUMA topology.",
2ed5d572
AD
713};
714PVE::JSONSchema::register_standard_option("pve-qm-numanode", $numadesc);
715
716for (my $i = 0; $i < $MAX_NUMA; $i++) {
717 $confdesc->{"numa$i"} = $numadesc;
718}
1e3baf05
DM
719
720my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
55034103
KT
721 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
722 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
6b64503e 723my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05 724
52261945
DM
725my $net_fmt_bridge_descr = <<__EOD__;
726Bridge to attach the network device to. The Proxmox VE standard bridge
727is called 'vmbr0'.
728
729If you do not specify a bridge, we create a kvm user (NATed) network
730device, which provides DHCP and DNS services. The following addresses
731are used:
732
733 10.0.2.2 Gateway
734 10.0.2.3 DNS Server
735 10.0.2.4 SMB Server
736
737The DHCP server assign addresses to the guest starting from 10.0.2.15.
738__EOD__
739
cd9c34d1
WB
740my $net_fmt = {
741 macaddr => {
742 type => 'string',
743 pattern => qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
52261945 744 description => "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
cd9c34d1
WB
745 format_description => "XX:XX:XX:XX:XX:XX",
746 optional => 1,
747 },
7f694a71
DM
748 model => {
749 type => 'string',
52261945 750 description => "Network Card Model. The 'virtio' model provides the best performance with very low CPU overhead. If your guest does not support this driver, it is usually best to use 'e1000'.",
7f694a71
DM
751 enum => $nic_model_list,
752 default_key => 1,
753 },
754 (map { $_ => { keyAlias => 'model', alias => 'macaddr' }} @$nic_model_list),
cd9c34d1
WB
755 bridge => {
756 type => 'string',
52261945 757 description => $net_fmt_bridge_descr,
cd9c34d1
WB
758 format_description => 'bridge',
759 optional => 1,
760 },
761 queues => {
762 type => 'integer',
763 minimum => 0, maximum => 16,
764 description => 'Number of packet queues to be used on the device.',
cd9c34d1
WB
765 optional => 1,
766 },
767 rate => {
768 type => 'number',
769 minimum => 0,
52261945 770 description => "Rate limit in mbps (megabytes per second) as floating point number.",
cd9c34d1
WB
771 optional => 1,
772 },
773 tag => {
774 type => 'integer',
9f41a659 775 minimum => 1, maximum => 4094,
cd9c34d1 776 description => 'VLAN tag to apply to packets on this interface.',
cd9c34d1
WB
777 optional => 1,
778 },
779 trunks => {
780 type => 'string',
781 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
782 description => 'VLAN trunks to pass through this interface.',
7f694a71 783 format_description => 'vlanid[;vlanid...]',
cd9c34d1
WB
784 optional => 1,
785 },
786 firewall => {
787 type => 'boolean',
788 description => 'Whether this interface should be protected by the firewall.',
cd9c34d1
WB
789 optional => 1,
790 },
791 link_down => {
792 type => 'boolean',
52261945 793 description => 'Whether this interface should be disconnected (like pulling the plug).',
cd9c34d1
WB
794 optional => 1,
795 },
796};
52261945 797
1e3baf05
DM
798my $netdesc = {
799 optional => 1,
7f694a71 800 type => 'string', format => $net_fmt,
52261945 801 description => "Specify network devices.",
1e3baf05 802};
52261945 803
1e3baf05
DM
804PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
805
0c9a7596
AD
806my $ipconfig_fmt = {
807 ip => {
808 type => 'string',
809 format => 'pve-ipv4-config',
810 format_description => 'IPv4Format/CIDR',
811 description => 'IPv4 address in CIDR format.',
812 optional => 1,
813 default => 'dhcp',
814 },
815 gw => {
816 type => 'string',
817 format => 'ipv4',
818 format_description => 'GatewayIPv4',
819 description => 'Default gateway for IPv4 traffic.',
820 optional => 1,
821 requires => 'ip',
822 },
823 ip6 => {
824 type => 'string',
825 format => 'pve-ipv6-config',
826 format_description => 'IPv6Format/CIDR',
827 description => 'IPv6 address in CIDR format.',
828 optional => 1,
829 default => 'dhcp',
830 },
831 gw6 => {
832 type => 'string',
833 format => 'ipv6',
834 format_description => 'GatewayIPv6',
835 description => 'Default gateway for IPv6 traffic.',
836 optional => 1,
837 requires => 'ip6',
838 },
839};
840PVE::JSONSchema::register_format('pve-qm-ipconfig', $ipconfig_fmt);
841my $ipconfigdesc = {
842 optional => 1,
843 type => 'string', format => 'pve-qm-ipconfig',
844 description => <<'EODESCR',
845cloud-init: Specify IP addresses and gateways for the corresponding interface.
846
847IP addresses use CIDR notation, gateways are optional but need an IP of the same type specified.
848
849The special string 'dhcp' can be used for IP addresses to use DHCP, in which case no explicit gateway should be provided.
850For IPv6 the special string 'auto' can be used to use stateless autoconfiguration.
851
852If cloud-init is enabled and neither an IPv4 nor an IPv6 address is specified, it defaults to using dhcp on IPv4.
853EODESCR
854};
855PVE::JSONSchema::register_standard_option("pve-qm-ipconfig", $netdesc);
856
1e3baf05
DM
857for (my $i = 0; $i < $MAX_NETS; $i++) {
858 $confdesc->{"net$i"} = $netdesc;
9ed7a77c
WB
859 $confdesc_cloudinit->{"ipconfig$i"} = $ipconfigdesc;
860}
861
862foreach my $key (keys %$confdesc_cloudinit) {
863 $confdesc->{$key} = $confdesc_cloudinit->{$key};
1e3baf05
DM
864}
865
ffa42b86
DC
866PVE::JSONSchema::register_format('pve-volume-id-or-qm-path', \&verify_volume_id_or_qm_path);
867sub verify_volume_id_or_qm_path {
822c8a07
WB
868 my ($volid, $noerr) = @_;
869
ffa42b86
DC
870 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m|^/|) {
871 return $volid;
872 }
873
874 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
822c8a07
WB
875 $volid = eval { PVE::JSONSchema::check_format('pve-volume-id', $volid, '') };
876 if ($@) {
877 return undef if $noerr;
878 die $@;
879 }
880 return $volid;
881}
882
1e3baf05 883my $drivename_hash;
19672434 884
0541eeb8
WB
885my %drivedesc_base = (
886 volume => { alias => 'file' },
887 file => {
93c0971c 888 type => 'string',
ffa42b86 889 format => 'pve-volume-id-or-qm-path',
0541eeb8
WB
890 default_key => 1,
891 format_description => 'volume',
892 description => "The drive's backing volume.",
893 },
894 media => {
895 type => 'string',
0541eeb8
WB
896 enum => [qw(cdrom disk)],
897 description => "The drive's media type.",
898 default => 'disk',
899 optional => 1
900 },
901 cyls => {
902 type => 'integer',
0541eeb8
WB
903 description => "Force the drive's physical geometry to have a specific cylinder count.",
904 optional => 1
905 },
906 heads => {
907 type => 'integer',
0541eeb8
WB
908 description => "Force the drive's physical geometry to have a specific head count.",
909 optional => 1
910 },
911 secs => {
912 type => 'integer',
0541eeb8
WB
913 description => "Force the drive's physical geometry to have a specific sector count.",
914 optional => 1
915 },
916 trans => {
917 type => 'string',
0541eeb8
WB
918 enum => [qw(none lba auto)],
919 description => "Force disk geometry bios translation mode.",
920 optional => 1,
921 },
922 snapshot => {
923 type => 'boolean',
bfb04cfc
WB
924 description => "Controls qemu's snapshot mode feature."
925 . " If activated, changes made to the disk are temporary and will"
926 . " be discarded when the VM is shutdown.",
0541eeb8
WB
927 optional => 1,
928 },
929 cache => {
930 type => 'string',
0541eeb8
WB
931 enum => [qw(none writethrough writeback unsafe directsync)],
932 description => "The drive's cache mode",
933 optional => 1,
934 },
c7d2b650 935 format => get_standard_option('pve-qm-image-format'),
0541eeb8 936 size => {
47c28a68
WB
937 type => 'string',
938 format => 'disk-size',
7f694a71 939 format_description => 'DiskSize',
0541eeb8
WB
940 description => "Disk size. This is purely informational and has no effect.",
941 optional => 1,
942 },
943 backup => {
944 type => 'boolean',
0541eeb8
WB
945 description => "Whether the drive should be included when making backups.",
946 optional => 1,
947 },
8557d01f 948 replicate => {
9edac22f 949 type => 'boolean',
3ab7663a 950 description => 'Whether the drive should considered for replication jobs.',
9edac22f
WL
951 optional => 1,
952 default => 1,
953 },
6e9d2550
AD
954 rerror => {
955 type => 'string',
956 enum => [qw(ignore report stop)],
957 description => 'Read error action.',
958 optional => 1,
959 },
0541eeb8
WB
960 werror => {
961 type => 'string',
0541eeb8
WB
962 enum => [qw(enospc ignore report stop)],
963 description => 'Write error action.',
964 optional => 1,
965 },
966 aio => {
967 type => 'string',
0541eeb8
WB
968 enum => [qw(native threads)],
969 description => 'AIO type to use.',
970 optional => 1,
971 },
972 discard => {
973 type => 'string',
0541eeb8
WB
974 enum => [qw(ignore on)],
975 description => 'Controls whether to pass discard/trim requests to the underlying storage.',
976 optional => 1,
977 },
978 detect_zeroes => {
979 type => 'boolean',
980 description => 'Controls whether to detect and try to optimize writes of zeroes.',
981 optional => 1,
982 },
983 serial => {
984 type => 'string',
46630a5f 985 format => 'urlencoded',
0541eeb8 986 format_description => 'serial',
ba8fc5d1
WB
987 maxLength => 20*3, # *3 since it's %xx url enoded
988 description => "The drive's reported serial number, url-encoded, up to 20 bytes long.",
0541eeb8 989 optional => 1,
ec82e3ee
CH
990 },
991 shared => {
992 type => 'boolean',
993 description => 'Mark this locally-managed volume as available on all nodes',
994 verbose_description => "Mark this locally-managed volume as available on all nodes.\n\nWARNING: This option does not share the volume automatically, it assumes it is shared already!",
995 optional => 1,
996 default => 0,
0541eeb8
WB
997 }
998);
999
0541eeb8
WB
1000my %iothread_fmt = ( iothread => {
1001 type => 'boolean',
0541eeb8
WB
1002 description => "Whether to use iothreads for this drive",
1003 optional => 1,
1004});
1005
1006my %model_fmt = (
1007 model => {
1008 type => 'string',
46630a5f 1009 format => 'urlencoded',
0541eeb8 1010 format_description => 'model',
ba8fc5d1
WB
1011 maxLength => 40*3, # *3 since it's %xx url enoded
1012 description => "The drive's reported model name, url-encoded, up to 40 bytes long.",
0541eeb8
WB
1013 optional => 1,
1014 },
1015);
1016
1017my %queues_fmt = (
1018 queues => {
1019 type => 'integer',
0541eeb8
WB
1020 description => "Number of queues.",
1021 minimum => 2,
1022 optional => 1
1023 }
1024);
1025
8e3c33ab
FG
1026my %scsiblock_fmt = (
1027 scsiblock => {
1028 type => 'boolean',
1029 description => "whether to use scsi-block for full passthrough of host block device\n\nWARNING: can lead to I/O errors in combination with low memory or high memory fragmentation on host",
1030 optional => 1,
1031 default => 0,
1032 },
1033);
1034
6c875f9f
NC
1035my %ssd_fmt = (
1036 ssd => {
1037 type => 'boolean',
1038 description => "Whether to expose this drive as an SSD, rather than a rotational hard disk.",
1039 optional => 1,
1040 },
1041);
1042
0541eeb8 1043my $add_throttle_desc = sub {
9196a8ec
WB
1044 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
1045 my $d = {
0541eeb8 1046 type => $type,
7f694a71 1047 format_description => $unit,
9196a8ec 1048 description => "Maximum $what in $longunit.",
0541eeb8
WB
1049 optional => 1,
1050 };
9196a8ec
WB
1051 $d->{minimum} = $minimum if defined($minimum);
1052 $drivedesc_base{$key} = $d;
0541eeb8
WB
1053};
1054# throughput: (leaky bucket)
d3f3f1b3
DM
1055$add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
1056$add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
1057$add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
1058$add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
1059$add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
1060$add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
1061$add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
1062$add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
1063$add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
0541eeb8
WB
1064
1065# pools: (pool of IO before throttling starts taking effect)
d3f3f1b3
DM
1066$add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
1067$add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
1068$add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
1069$add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
1070$add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
1071$add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
9196a8ec
WB
1072
1073# burst lengths
fb8e95a2
WB
1074$add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
1075$add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
1076$add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
1077$add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
1078$add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
1079$add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
1080
1081# legacy support
1082$drivedesc_base{'bps_rd_length'} = { alias => 'bps_rd_max_length' };
1083$drivedesc_base{'bps_wr_length'} = { alias => 'bps_wr_max_length' };
1084$drivedesc_base{'iops_rd_length'} = { alias => 'iops_rd_max_length' };
1085$drivedesc_base{'iops_wr_length'} = { alias => 'iops_wr_max_length' };
0541eeb8
WB
1086
1087my $ide_fmt = {
1088 %drivedesc_base,
0541eeb8 1089 %model_fmt,
6c875f9f 1090 %ssd_fmt,
0541eeb8 1091};
b799312f 1092PVE::JSONSchema::register_format("pve-qm-ide", $ide_fmt);
0541eeb8 1093
1e3baf05
DM
1094my $idedesc = {
1095 optional => 1,
0541eeb8 1096 type => 'string', format => $ide_fmt,
3c770faa 1097 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1e3baf05
DM
1098};
1099PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
1100
0541eeb8
WB
1101my $scsi_fmt = {
1102 %drivedesc_base,
1103 %iothread_fmt,
1104 %queues_fmt,
8e3c33ab 1105 %scsiblock_fmt,
6c875f9f 1106 %ssd_fmt,
0541eeb8 1107};
1e3baf05
DM
1108my $scsidesc = {
1109 optional => 1,
0541eeb8 1110 type => 'string', format => $scsi_fmt,
3c770faa 1111 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1e3baf05
DM
1112};
1113PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
1114
0541eeb8
WB
1115my $sata_fmt = {
1116 %drivedesc_base,
6c875f9f 1117 %ssd_fmt,
0541eeb8 1118};
cdb0931f
DA
1119my $satadesc = {
1120 optional => 1,
0541eeb8 1121 type => 'string', format => $sata_fmt,
3c770faa 1122 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
cdb0931f
DA
1123};
1124PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
1125
0541eeb8
WB
1126my $virtio_fmt = {
1127 %drivedesc_base,
1128 %iothread_fmt,
0541eeb8 1129};
1e3baf05
DM
1130my $virtiodesc = {
1131 optional => 1,
0541eeb8 1132 type => 'string', format => $virtio_fmt,
3c770faa 1133 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1e3baf05
DM
1134};
1135PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
1136
0541eeb8
WB
1137my $alldrive_fmt = {
1138 %drivedesc_base,
0541eeb8
WB
1139 %iothread_fmt,
1140 %model_fmt,
1141 %queues_fmt,
8e3c33ab 1142 %scsiblock_fmt,
6c875f9f 1143 %ssd_fmt,
0541eeb8
WB
1144};
1145
6470743f
DC
1146my $efidisk_fmt = {
1147 volume => { alias => 'file' },
1148 file => {
1149 type => 'string',
1150 format => 'pve-volume-id-or-qm-path',
1151 default_key => 1,
1152 format_description => 'volume',
1153 description => "The drive's backing volume.",
1154 },
c7d2b650 1155 format => get_standard_option('pve-qm-image-format'),
6470743f
DC
1156 size => {
1157 type => 'string',
1158 format => 'disk-size',
1159 format_description => 'DiskSize',
1160 description => "Disk size. This is purely informational and has no effect.",
1161 optional => 1,
1162 },
1163};
1164
1165my $efidisk_desc = {
1166 optional => 1,
1167 type => 'string', format => $efidisk_fmt,
1168 description => "Configure a Disk for storing EFI vars",
1169};
1170
1171PVE::JSONSchema::register_standard_option("pve-qm-efidisk", $efidisk_desc);
1172
ff6ffe20 1173my $usb_fmt = {
a6b9aee4
DC
1174 host => {
1175 default_key => 1,
1176 type => 'string', format => 'pve-qm-usb-device',
1177 format_description => 'HOSTUSBDEVICE|spice',
52261945
DM
1178 description => <<EODESCR,
1179The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
1180
1181 'bus-port(.port)*' (decimal numbers) or
1182 'vendor_id:product_id' (hexadeciaml numbers) or
1183 'spice'
1184
1185You can use the 'lsusb -t' command to list existing usb devices.
1186
1187NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1188
1189The value 'spice' can be used to add a usb redirection devices for spice.
1190EODESCR
a6b9aee4
DC
1191 },
1192 usb3 => {
1193 optional => 1,
1194 type => 'boolean',
52261945
DM
1195 description => "Specifies whether if given host option is a USB3 device or port (this does currently not work reliably with spice redirection and is then ignored).",
1196 default => 0,
a6b9aee4
DC
1197 },
1198};
1199
1e3baf05
DM
1200my $usbdesc = {
1201 optional => 1,
ff6ffe20 1202 type => 'string', format => $usb_fmt,
52261945 1203 description => "Configure an USB device (n is 0 to 4).",
1e3baf05
DM
1204};
1205PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
1206
1f4f447b
WB
1207# NOTE: the match-groups of this regex are used in parse_hostpci
1208my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1209my $hostpci_fmt = {
1210 host => {
1211 default_key => 1,
1212 type => 'string',
1213 pattern => qr/$PCIRE(;$PCIRE)*/,
1214 format_description => 'HOSTPCIID[;HOSTPCIID2...]',
52261945
DM
1215 description => <<EODESCR,
1216Host PCI device pass through. The PCI ID of a host's PCI device or a list
1217of PCI virtual functions of the host. HOSTPCIID syntax is:
1218
1219'bus:dev.func' (hexadecimal numbers)
1220
1221You can us the 'lspci' command to list existing PCI devices.
52261945 1222EODESCR
1f4f447b
WB
1223 },
1224 rombar => {
1225 type => 'boolean',
52261945 1226 description => "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1f4f447b
WB
1227 optional => 1,
1228 default => 1,
1229 },
456a6fec
AD
1230 romfile => {
1231 type => 'string',
1232 pattern => '[^,;]+',
1233 format_description => 'string',
1234 description => "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1235 optional => 1,
1236 },
1f4f447b
WB
1237 pcie => {
1238 type => 'boolean',
52261945 1239 description => "Choose the PCI-express bus (needs the 'q35' machine model).",
1f4f447b
WB
1240 optional => 1,
1241 default => 0,
1242 },
1243 'x-vga' => {
1244 type => 'boolean',
52261945 1245 description => "Enable vfio-vga device support.",
1f4f447b
WB
1246 optional => 1,
1247 default => 0,
1248 },
1249};
1250PVE::JSONSchema::register_format('pve-qm-hostpci', $hostpci_fmt);
1251
040b06b7
DA
1252my $hostpcidesc = {
1253 optional => 1,
1254 type => 'string', format => 'pve-qm-hostpci',
52261945 1255 description => "Map host PCI devices into guest.",
faab5306
DM
1256 verbose_description => <<EODESCR,
1257Map host PCI devices into guest.
1258
1259NOTE: This option allows direct access to host hardware. So it is no longer
1260possible to migrate such machines - use with special care.
1261
1262CAUTION: Experimental! User reported problems with this option.
1263EODESCR
040b06b7
DA
1264};
1265PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
1266
bae179aa
DA
1267my $serialdesc = {
1268 optional => 1,
ca0cef26 1269 type => 'string',
1b0b51ed 1270 pattern => '(/dev/.+|socket)',
52261945
DM
1271 description => "Create a serial device inside the VM (n is 0 to 3)",
1272 verbose_description => <<EODESCR,
52261945
DM
1273Create a serial device inside the VM (n is 0 to 3), and pass through a
1274host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1275host side (use 'qm terminal' to open a terminal connection).
bae179aa 1276
8a61e0fd 1277NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
bae179aa 1278
52261945 1279CAUTION: Experimental! User reported problems with this option.
bae179aa
DA
1280EODESCR
1281};
bae179aa 1282
1989a89c
DA
1283my $paralleldesc= {
1284 optional => 1,
ca0cef26 1285 type => 'string',
9ecc8431 1286 pattern => '/dev/parport\d+|/dev/usb/lp\d+',
52261945
DM
1287 description => "Map host parallel devices (n is 0 to 2).",
1288 verbose_description => <<EODESCR,
19672434 1289Map host parallel devices (n is 0 to 2).
1989a89c 1290
8a61e0fd 1291NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1989a89c 1292
52261945 1293CAUTION: Experimental! User reported problems with this option.
1989a89c
DA
1294EODESCR
1295};
1989a89c
DA
1296
1297for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1298 $confdesc->{"parallel$i"} = $paralleldesc;
1299}
1300
bae179aa
DA
1301for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1302 $confdesc->{"serial$i"} = $serialdesc;
1303}
1304
040b06b7
DA
1305for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1306 $confdesc->{"hostpci$i"} = $hostpcidesc;
1307}
1e3baf05
DM
1308
1309for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1310 $drivename_hash->{"ide$i"} = 1;
1311 $confdesc->{"ide$i"} = $idedesc;
1312}
1313
cdb0931f
DA
1314for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1315 $drivename_hash->{"sata$i"} = 1;
1316 $confdesc->{"sata$i"} = $satadesc;
1317}
1318
1e3baf05
DM
1319for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1320 $drivename_hash->{"scsi$i"} = 1;
1321 $confdesc->{"scsi$i"} = $scsidesc ;
1322}
1323
1324for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1325 $drivename_hash->{"virtio$i"} = 1;
1326 $confdesc->{"virtio$i"} = $virtiodesc;
1327}
1328
6470743f
DC
1329$drivename_hash->{efidisk0} = 1;
1330$confdesc->{efidisk0} = $efidisk_desc;
1331
1e3baf05
DM
1332for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1333 $confdesc->{"usb$i"} = $usbdesc;
1334}
1335
1336my $unuseddesc = {
1337 optional => 1,
1338 type => 'string', format => 'pve-volume-id',
52261945 1339 description => "Reference to unused volumes. This is used internally, and should not be modified manually.",
1e3baf05
DM
1340};
1341
1342for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1343 $confdesc->{"unused$i"} = $unuseddesc;
1344}
1345
1346my $kvm_api_version = 0;
1347
1348sub kvm_version {
1e3baf05
DM
1349 return $kvm_api_version if $kvm_api_version;
1350
646f2df4
WB
1351 open my $fh, '<', '/dev/kvm'
1352 or return undef;
1e3baf05 1353
646f2df4
WB
1354 # 0xae00 => KVM_GET_API_VERSION
1355 $kvm_api_version = ioctl($fh, 0xae00, 0);
1e3baf05 1356
646f2df4 1357 return $kvm_api_version;
1e3baf05
DM
1358}
1359
1360my $kvm_user_version;
1361
1362sub kvm_user_version {
1363
1364 return $kvm_user_version if $kvm_user_version;
1365
1366 $kvm_user_version = 'unknown';
1367
09b11429
TL
1368 my $code = sub {
1369 my $line = shift;
1370 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1371 $kvm_user_version = $2;
1372 }
1373 };
19672434 1374
09b11429
TL
1375 eval { run_command("kvm -version", outfunc => $code); };
1376 warn $@ if $@;
1e3baf05
DM
1377
1378 return $kvm_user_version;
1379
1380}
1381
1382my $kernel_has_vhost_net = -c '/dev/vhost-net';
1383
74479ee9 1384sub valid_drive_names {
1e3baf05 1385 # order is important - used to autoselect boot disk
19672434 1386 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 1387 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f 1388 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
6470743f
DC
1389 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1390 'efidisk0');
1e3baf05
DM
1391}
1392
74479ee9 1393sub is_valid_drivename {
1e3baf05
DM
1394 my $dev = shift;
1395
6b64503e 1396 return defined($drivename_hash->{$dev});
1e3baf05
DM
1397}
1398
1399sub option_exists {
1400 my $key = shift;
1401 return defined($confdesc->{$key});
19672434 1402}
1e3baf05
DM
1403
1404sub nic_models {
1405 return $nic_model_list;
1406}
1407
1408sub os_list_description {
1409
1410 return {
1411 other => 'Other',
1412 wxp => 'Windows XP',
1413 w2k => 'Windows 2000',
1414 w2k3 =>, 'Windows 2003',
1415 w2k8 => 'Windows 2008',
1416 wvista => 'Windows Vista',
1417 win7 => 'Windows 7',
a70ebde3 1418 win8 => 'Windows 8/2012',
0cb9971e 1419 win10 => 'Windows 10/2016',
1e3baf05
DM
1420 l24 => 'Linux 2.4',
1421 l26 => 'Linux 2.6',
19672434 1422 };
1e3baf05
DM
1423}
1424
1e3baf05
DM
1425my $cdrom_path;
1426
1427sub get_cdrom_path {
1428
1429 return $cdrom_path if $cdrom_path;
1430
1431 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
1432 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
1433 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
1434}
1435
1436sub get_iso_path {
1437 my ($storecfg, $vmid, $cdrom) = @_;
1438
1439 if ($cdrom eq 'cdrom') {
1440 return get_cdrom_path();
1441 } elsif ($cdrom eq 'none') {
1442 return '';
1443 } elsif ($cdrom =~ m|^/|) {
1444 return $cdrom;
1445 } else {
6b64503e 1446 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
1447 }
1448}
1449
1450# try to convert old style file names to volume IDs
1451sub filename_to_volume_id {
1452 my ($vmid, $file, $media) = @_;
1453
0c9a7596 1454 if (!($file eq 'none' || $file eq 'cdrom' ||
1e3baf05 1455 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 1456
1e3baf05 1457 return undef if $file =~ m|/|;
19672434 1458
1e3baf05
DM
1459 if ($media && $media eq 'cdrom') {
1460 $file = "local:iso/$file";
1461 } else {
1462 $file = "local:$vmid/$file";
1463 }
1464 }
1465
1466 return $file;
1467}
1468
1469sub verify_media_type {
1470 my ($opt, $vtype, $media) = @_;
1471
1472 return if !$media;
1473
1474 my $etype;
1475 if ($media eq 'disk') {
a125592c 1476 $etype = 'images';
1e3baf05
DM
1477 } elsif ($media eq 'cdrom') {
1478 $etype = 'iso';
1479 } else {
1480 die "internal error";
1481 }
1482
1483 return if ($vtype eq $etype);
19672434 1484
1e3baf05
DM
1485 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
1486}
1487
1488sub cleanup_drive_path {
1489 my ($opt, $storecfg, $drive) = @_;
1490
1491 # try to convert filesystem paths to volume IDs
1492
1493 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
1494 ($drive->{file} !~ m|^/dev/.+|) &&
1495 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 1496 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
1497 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
1498 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1499 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
1500 verify_media_type($opt, $vtype, $drive->{media});
1501 $drive->{file} = $volid;
1502 }
1503
1504 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
1505}
1506
b3c2bdd1
DM
1507sub parse_hotplug_features {
1508 my ($data) = @_;
1509
1510 my $res = {};
1511
1512 return $res if $data eq '0';
a1b7d579 1513
b3c2bdd1
DM
1514 $data = $confdesc->{hotplug}->{default} if $data eq '1';
1515
45827685 1516 foreach my $feature (PVE::Tools::split_list($data)) {
b3c2bdd1
DM
1517 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1518 $res->{$1} = 1;
1519 } else {
596a0a20 1520 die "invalid hotplug feature '$feature'\n";
b3c2bdd1
DM
1521 }
1522 }
1523 return $res;
1524}
1525
1526PVE::JSONSchema::register_format('pve-hotplug-features', \&pve_verify_hotplug_features);
1527sub pve_verify_hotplug_features {
1528 my ($value, $noerr) = @_;
1529
1530 return $value if parse_hotplug_features($value);
1531
1532 return undef if $noerr;
1533
1534 die "unable to parse hotplug option\n";
1535}
1536
1e3baf05
DM
1537# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1538# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 1539# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
6e47c3b4
WB
1540# [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1541# [,iothread=on][,serial=serial][,model=model]
1e3baf05
DM
1542
1543sub parse_drive {
1544 my ($key, $data) = @_;
1545
0541eeb8 1546 my ($interface, $index);
19672434 1547
0541eeb8
WB
1548 if ($key =~ m/^([^\d]+)(\d+)$/) {
1549 $interface = $1;
1550 $index = $2;
1e3baf05
DM
1551 } else {
1552 return undef;
1553 }
1554
0541eeb8
WB
1555 my $desc = $key =~ /^unused\d+$/ ? $alldrive_fmt
1556 : $confdesc->{$key}->{format};
1557 if (!$desc) {
1558 warn "invalid drive key: $key\n";
1559 return undef;
1560 }
1561 my $res = eval { PVE::JSONSchema::parse_property_string($desc, $data) };
1562 return undef if !$res;
1563 $res->{interface} = $interface;
1564 $res->{index} = $index;
1565
1566 my $error = 0;
1567 foreach my $opt (qw(bps bps_rd bps_wr)) {
1568 if (my $bps = defined(delete $res->{$opt})) {
1569 if (defined($res->{"m$opt"})) {
1570 warn "both $opt and m$opt specified\n";
1571 ++$error;
1572 next;
1e3baf05 1573 }
0541eeb8 1574 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1e3baf05
DM
1575 }
1576 }
9196a8ec
WB
1577
1578 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1579 for my $requirement (
fb8e95a2
WB
1580 [mbps_max => 'mbps'],
1581 [mbps_rd_max => 'mbps_rd'],
1582 [mbps_wr_max => 'mbps_wr'],
1583 [miops_max => 'miops'],
1584 [miops_rd_max => 'miops_rd'],
1585 [miops_wr_max => 'miops_wr'],
9196a8ec
WB
1586 [bps_max_length => 'mbps_max'],
1587 [bps_rd_max_length => 'mbps_rd_max'],
1588 [bps_wr_max_length => 'mbps_wr_max'],
1589 [iops_max_length => 'iops_max'],
1590 [iops_rd_max_length => 'iops_rd_max'],
1591 [iops_wr_max_length => 'iops_wr_max']) {
1592 my ($option, $requires) = @$requirement;
1593 if ($res->{$option} && !$res->{$requires}) {
1594 warn "$option requires $requires\n";
1595 ++$error;
1596 }
1597 }
1598
0541eeb8 1599 return undef if $error;
be190583 1600
9bf371a6
DM
1601 return undef if $res->{mbps_rd} && $res->{mbps};
1602 return undef if $res->{mbps_wr} && $res->{mbps};
affd2f88
AD
1603 return undef if $res->{iops_rd} && $res->{iops};
1604 return undef if $res->{iops_wr} && $res->{iops};
74edd76b 1605
1e3baf05
DM
1606 if ($res->{media} && ($res->{media} eq 'cdrom')) {
1607 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 1608 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
1609 return undef if $res->{interface} eq 'virtio';
1610 }
1611
0541eeb8
WB
1612 if (my $size = $res->{size}) {
1613 return undef if !defined($res->{size} = PVE::JSONSchema::parse_size($size));
1e3baf05
DM
1614 }
1615
1616 return $res;
1617}
1618
1e3baf05
DM
1619sub print_drive {
1620 my ($vmid, $drive) = @_;
0541eeb8
WB
1621 my $data = { %$drive };
1622 delete $data->{$_} for qw(index interface);
1623 return PVE::JSONSchema::print_property_string($data, $alldrive_fmt);
1e3baf05
DM
1624}
1625
28ef82d3
DM
1626sub scsi_inquiry {
1627 my($fh, $noerr) = @_;
1628
1629 my $SG_IO = 0x2285;
1630 my $SG_GET_VERSION_NUM = 0x2282;
1631
1632 my $versionbuf = "\x00" x 8;
1633 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1634 if (!$ret) {
1635 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1636 return undef;
1637 }
97d62eb7 1638 my $version = unpack("I", $versionbuf);
28ef82d3
DM
1639 if ($version < 30000) {
1640 die "scsi generic interface too old\n" if !$noerr;
1641 return undef;
1642 }
97d62eb7 1643
28ef82d3
DM
1644 my $buf = "\x00" x 36;
1645 my $sensebuf = "\x00" x 8;
f334aa3e 1646 my $cmd = pack("C x3 C x1", 0x12, 36);
97d62eb7 1647
28ef82d3
DM
1648 # see /usr/include/scsi/sg.h
1649 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1650
97d62eb7
DM
1651 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1652 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
1653 $cmd, $sensebuf, 6000);
1654
1655 $ret = ioctl($fh, $SG_IO, $packet);
1656 if (!$ret) {
1657 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1658 return undef;
1659 }
97d62eb7 1660
28ef82d3
DM
1661 my @res = unpack($sg_io_hdr_t, $packet);
1662 if ($res[17] || $res[18]) {
1663 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1664 return undef;
1665 }
1666
1667 my $res = {};
09984754 1668 (my $byte0, my $byte1, $res->{vendor},
28ef82d3
DM
1669 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1670
09984754
DM
1671 $res->{removable} = $byte1 & 128 ? 1 : 0;
1672 $res->{type} = $byte0 & 31;
1673
28ef82d3
DM
1674 return $res;
1675}
1676
1677sub path_is_scsi {
1678 my ($path) = @_;
1679
1680 my $fh = IO::File->new("+<$path") || return undef;
1681 my $res = scsi_inquiry($fh, 1);
1682 close($fh);
1683
1684 return $res;
1685}
1686
db656e5f
DM
1687sub machine_type_is_q35 {
1688 my ($conf) = @_;
b467f79a 1689
db656e5f
DM
1690 return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
1691}
1692
1693sub print_tabletdevice_full {
d559309f 1694 my ($conf, $arch) = @_;
b467f79a 1695
db656e5f
DM
1696 my $q35 = machine_type_is_q35($conf);
1697
1698 # we use uhci for old VMs because tablet driver was buggy in older qemu
d559309f
WB
1699 my $usbbus;
1700 if (machine_type_is_q35($conf) || $arch eq 'aarch64') {
1701 $usbbus = 'ehci';
1702 } else {
1703 $usbbus = 'uhci';
1704 }
b467f79a 1705
db656e5f
DM
1706 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1707}
1708
d559309f
WB
1709sub print_keyboarddevice_full {
1710 my ($conf, $arch, $machine) = @_;
1711
1712 return undef if $arch ne 'aarch64';
1713
1714 return "usb-kbd,id=keyboard,bus=ehci.0,port=2";
1715}
1716
ca916ecc 1717sub print_drivedevice_full {
d559309f 1718 my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_;
ca916ecc
DA
1719
1720 my $device = '';
1721 my $maxdev = 0;
19672434 1722
ca916ecc 1723 if ($drive->{interface} eq 'virtio') {
d559309f 1724 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges, $arch, $machine_type);
2ed36a41 1725 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
51f492cd 1726 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread};
2ed36a41 1727 } elsif ($drive->{interface} eq 'scsi') {
6731a4cf 1728
ee034f5c 1729 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
2ed36a41
DM
1730 my $unit = $drive->{index} % $maxdev;
1731 my $devicetype = 'hd';
69bcf246
WB
1732 my $path = '';
1733 if (drive_is_cdrom($drive)) {
1734 $devicetype = 'cd';
29b19529 1735 } else {
69bcf246
WB
1736 if ($drive->{file} =~ m|^/|) {
1737 $path = $drive->{file};
1738 if (my $info = path_is_scsi($path)) {
8e3c33ab 1739 if ($info->{type} == 0 && $drive->{scsiblock}) {
69bcf246
WB
1740 $devicetype = 'block';
1741 } elsif ($info->{type} == 1) { # tape
1742 $devicetype = 'generic';
1743 }
1744 }
1745 } else {
1746 $path = PVE::Storage::path($storecfg, $drive->{file});
1747 }
1748
1749 if($path =~ m/^iscsi\:\/\//){
1750 $devicetype = 'generic';
1751 }
1752 }
1753
1754 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)){
1755 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1756 } else {
1757 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1758 }
cdd20088 1759
6c875f9f
NC
1760 if ($drive->{ssd} && ($devicetype eq 'block' || $devicetype eq 'hd')) {
1761 $device .= ",rotation_rate=1";
1762 }
1763
1764 } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') {
1765 my $maxdev = ($drive->{interface} eq 'sata') ? $MAX_SATA_DISKS : 2;
2ed36a41
DM
1766 my $controller = int($drive->{index} / $maxdev);
1767 my $unit = $drive->{index} % $maxdev;
1768 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
1769
6c875f9f
NC
1770 $device = "ide-$devicetype";
1771 if ($drive->{interface} eq 'ide') {
1772 $device .= ",bus=ide.$controller,unit=$unit";
1773 } else {
1774 $device .= ",bus=ahci$controller.$unit";
1775 }
1776 $device .= ",drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1777
1778 if ($devicetype eq 'hd') {
1779 if (my $model = $drive->{model}) {
1780 $model = URI::Escape::uri_unescape($model);
1781 $device .= ",model=$model";
1782 }
1783 if ($drive->{ssd}) {
1784 $device .= ",rotation_rate=1";
1785 }
0f2812c2 1786 }
2ed36a41
DM
1787 } elsif ($drive->{interface} eq 'usb') {
1788 die "implement me";
1789 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1790 } else {
1791 die "unsupported interface type";
ca916ecc
DA
1792 }
1793
3b408e82
DM
1794 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1795
a70e7e6c
TL
1796 if (my $serial = $drive->{serial}) {
1797 $serial = URI::Escape::uri_unescape($serial);
1798 $device .= ",serial=$serial";
1799 }
1800
1801
ca916ecc
DA
1802 return $device;
1803}
1804
15b21acc 1805sub get_initiator_name {
46f58b5f 1806 my $initiator;
15b21acc 1807
46f58b5f
DM
1808 my $fh = IO::File->new('/etc/iscsi/initiatorname.iscsi') || return undef;
1809 while (defined(my $line = <$fh>)) {
1810 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
15b21acc
MR
1811 $initiator = $1;
1812 last;
1813 }
46f58b5f
DM
1814 $fh->close();
1815
15b21acc
MR
1816 return $initiator;
1817}
1818
1e3baf05
DM
1819sub print_drive_full {
1820 my ($storecfg, $vmid, $drive) = @_;
1821
d81f0f09
DM
1822 my $path;
1823 my $volid = $drive->{file};
1824 my $format;
1825
1826 if (drive_is_cdrom($drive)) {
1827 $path = get_iso_path($storecfg, $vmid, $volid);
1828 } else {
1829 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1830 if ($storeid) {
1831 $path = PVE::Storage::path($storecfg, $volid);
1832 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
1833 $format = qemu_img_format($scfg, $volname);
1834 } else {
1835 $path = $volid;
5b61bff2 1836 $format = "raw";
d81f0f09
DM
1837 }
1838 }
1839
1e3baf05 1840 my $opts = '';
8a267708 1841 my @qemu_drive_options = qw(heads secs cyls trans media format cache rerror werror aio discard);
1e3baf05 1842 foreach my $o (@qemu_drive_options) {
5fc74861 1843 $opts .= ",$o=$drive->{$o}" if defined($drive->{$o});
19672434 1844 }
8a267708
DC
1845
1846 # snapshot only accepts on|off
1847 if (defined($drive->{snapshot})) {
1848 my $v = $drive->{snapshot} ? 'on' : 'off';
1849 $opts .= ",snapshot=$v";
1850 }
1851
fb8e95a2
WB
1852 foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
1853 my ($dir, $qmpname) = @$type;
1854 if (my $v = $drive->{"mbps$dir"}) {
1855 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1856 }
1857 if (my $v = $drive->{"mbps${dir}_max"}) {
1858 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1859 }
1860 if (my $v = $drive->{"bps${dir}_max_length"}) {
1861 $opts .= ",throttling.bps$qmpname-max-length=$v";
1862 }
1863 if (my $v = $drive->{"iops${dir}"}) {
1864 $opts .= ",throttling.iops$qmpname=$v";
1865 }
1866 if (my $v = $drive->{"iops${dir}_max"}) {
8aca1654 1867 $opts .= ",throttling.iops$qmpname-max=$v";
fb8e95a2
WB
1868 }
1869 if (my $v = $drive->{"iops${dir}_max_length"}) {
8aca1654 1870 $opts .= ",throttling.iops$qmpname-max-length=$v";
fb8e95a2
WB
1871 }
1872 }
1873
d81f0f09
DM
1874 $opts .= ",format=$format" if $format && !$drive->{format};
1875
b2ee900e
WB
1876 my $cache_direct = 0;
1877
1878 if (my $cache = $drive->{cache}) {
1879 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1880 } elsif (!drive_is_cdrom($drive)) {
1881 $opts .= ",cache=none";
1882 $cache_direct = 1;
1883 }
1884
1885 # aio native works only with O_DIRECT
1886 if (!$drive->{aio}) {
1887 if($cache_direct) {
1888 $opts .= ",aio=native";
1889 } else {
1890 $opts .= ",aio=threads";
1891 }
1892 }
11490cf2 1893
6e47c3b4
WB
1894 if (!drive_is_cdrom($drive)) {
1895 my $detectzeroes;
7d4e30f3 1896 if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
6e47c3b4
WB
1897 $detectzeroes = 'off';
1898 } elsif ($drive->{discard}) {
1899 $detectzeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
1900 } else {
1901 # This used to be our default with discard not being specified:
1902 $detectzeroes = 'on';
1903 }
1904 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1905 }
f1e05305 1906
1e3baf05
DM
1907 my $pathinfo = $path ? "file=$path," : '';
1908
3ebfcc86 1909 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1910}
1911
cc4d6182 1912sub print_netdevice_full {
d559309f 1913 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files, $arch, $machine_type) = @_;
cc4d6182
DA
1914
1915 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1916
1917 my $device = $net->{model};
1918 if ($net->{model} eq 'virtio') {
1919 $device = 'virtio-net-pci';
1920 };
1921
d559309f 1922 my $pciaddr = print_pci_addr("$netid", $bridges, $arch, $machine_type);
5e2068d2 1923 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
a9410357
AD
1924 if ($net->{queues} && $net->{queues} > 1 && $net->{model} eq 'virtio'){
1925 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1926 my $vectors = $net->{queues} * 2 + 2;
1927 $tmpstr .= ",vectors=$vectors,mq=on";
1928 }
cc4d6182 1929 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
ba9e1000
DM
1930
1931 if ($use_old_bios_files) {
1932 my $romfile;
1933 if ($device eq 'virtio-net-pci') {
1934 $romfile = 'pxe-virtio.rom';
1935 } elsif ($device eq 'e1000') {
1936 $romfile = 'pxe-e1000.rom';
1937 } elsif ($device eq 'ne2k') {
1938 $romfile = 'pxe-ne2k_pci.rom';
1939 } elsif ($device eq 'pcnet') {
1940 $romfile = 'pxe-pcnet.rom';
1941 } elsif ($device eq 'rtl8139') {
1942 $romfile = 'pxe-rtl8139.rom';
1943 }
1944 $tmpstr .= ",romfile=$romfile" if $romfile;
1945 }
1946
cc4d6182
DA
1947 return $tmpstr;
1948}
1949
1950sub print_netdev_full {
d559309f 1951 my ($vmid, $conf, $arch, $net, $netid, $hotplug) = @_;
cc4d6182
DA
1952
1953 my $i = '';
1954 if ($netid =~ m/^net(\d+)$/) {
1955 $i = int($1);
1956 }
1957
1958 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1959
1960 my $ifname = "tap${vmid}i$i";
1961
1962 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1963 die "interface name '$ifname' is too long (max 15 character)\n"
1964 if length($ifname) >= 16;
1965
1966 my $vhostparam = '';
6f0cb675
WB
1967 if (is_native($arch)) {
1968 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1969 }
cc4d6182
DA
1970
1971 my $vmname = $conf->{name} || "vm$vmid";
1972
a9410357 1973 my $netdev = "";
208ba94e 1974 my $script = $hotplug ? "pve-bridge-hotplug" : "pve-bridge";
a9410357 1975
cc4d6182 1976 if ($net->{bridge}) {
208ba94e 1977 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
cc4d6182 1978 } else {
a9410357 1979 $netdev = "type=user,id=$netid,hostname=$vmname";
cc4d6182 1980 }
a9410357
AD
1981
1982 $netdev .= ",queues=$net->{queues}" if ($net->{queues} && $net->{model} eq 'virtio');
1983
1984 return $netdev;
cc4d6182 1985}
1e3baf05 1986
0efb537e
AD
1987
1988sub print_cpu_device {
1989 my ($conf, $id) = @_;
1990
74c02ef7
PA
1991 my $kvm = $conf->{kvm} // 1;
1992 my $cpu = $kvm ? "kvm64" : "qemu64";
0efb537e
AD
1993 if (my $cputype = $conf->{cpu}) {
1994 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
1995 or die "Cannot parse cpu description: $cputype\n";
1996 $cpu = $cpuconf->{cputype};
1997 }
1998
0efb537e
AD
1999 my $cores = $conf->{cores} || 1;
2000
2001 my $current_core = ($id - 1) % $cores;
7032e08c 2002 my $current_socket = int(($id - 1 - $current_core)/$cores);
0efb537e
AD
2003
2004 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
2005}
2006
55655ebc
DC
2007my $vga_map = {
2008 'cirrus' => 'cirrus-vga',
2009 'std' => 'VGA',
2010 'vmware' => 'vmware-svga',
2011 'virtio' => 'virtio-vga',
2012};
2013
2014sub print_vga_device {
d559309f 2015 my ($conf, $vga, $arch, $machine, $id, $qxlnum, $bridges) = @_;
55655ebc
DC
2016
2017 my $type = $vga_map->{$vga->{type}};
d559309f
WB
2018 if ($type eq 'virtio-vga' && $arch eq 'aarch64') {
2019 $type = 'virtio-gpu';
2020 }
55655ebc
DC
2021 my $vgamem_mb = $vga->{memory};
2022 if ($qxlnum) {
2023 $type = $id ? 'qxl' : 'qxl-vga';
2024 }
2025 die "no devicetype for $vga->{type}\n" if !$type;
2026
2027 my $memory = "";
2028 if ($vgamem_mb) {
2029 if ($vga->{type} eq 'virtio') {
2030 my $bytes = PVE::Tools::convert_size($vgamem_mb, "mb" => "b");
2031 $memory = ",max_hostmem=$bytes";
2032 } elsif ($qxlnum) {
2033 # from https://www.spice-space.org/multiple-monitors.html
2034 $memory = ",vgamem_mb=$vga->{memory}";
2035 my $ram = $vgamem_mb * 4;
2036 my $vram = $vgamem_mb * 2;
2037 $memory .= ",ram_size_mb=$ram,vram_size_mb=$vram";
2038 } else {
2039 $memory = ",vgamem_mb=$vga->{memory}";
2040 }
2041 } elsif ($qxlnum && $id) {
2042 $memory = ",ram_size=67108864,vram_size=33554432";
2043 }
2044
2045 my $q35 = machine_type_is_q35($conf);
2046 my $vgaid = "vga" . ($id // '');
2047 my $pciaddr;
daadd5a4 2048
55655ebc 2049 if ($q35 && $vgaid eq 'vga') {
daadd5a4 2050 # the first display uses pcie.0 bus on q35 machines
d559309f 2051 $pciaddr = print_pcie_addr($vgaid, $bridges, $arch, $machine);
55655ebc 2052 } else {
d559309f 2053 $pciaddr = print_pci_addr($vgaid, $bridges, $arch, $machine);
55655ebc
DC
2054 }
2055
2056 return "$type,id=${vgaid}${memory}${pciaddr}";
2057}
2058
9ed7a77c
WB
2059sub drive_is_cloudinit {
2060 my ($drive) = @_;
2061 return $drive->{file} =~ m@[:/]vm-\d+-cloudinit(?:\.$QEMU_FORMAT_RE)?$@;
2062}
2063
1e3baf05 2064sub drive_is_cdrom {
9c52f5ed
WB
2065 my ($drive, $exclude_cloudinit) = @_;
2066
9ed7a77c 2067 return 0 if $exclude_cloudinit && drive_is_cloudinit($drive);
1e3baf05
DM
2068
2069 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
2070
2071}
2072
ffc0d8c7
WB
2073sub parse_number_sets {
2074 my ($set) = @_;
2075 my $res = [];
2076 foreach my $part (split(/;/, $set)) {
2077 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
2078 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
2079 push @$res, [ $1, $2 ];
2ed5d572 2080 } else {
ffc0d8c7 2081 die "invalid range: $part\n";
2ed5d572
AD
2082 }
2083 }
ffc0d8c7
WB
2084 return $res;
2085}
2ed5d572 2086
ffc0d8c7
WB
2087sub parse_numa {
2088 my ($data) = @_;
2089
2090 my $res = PVE::JSONSchema::parse_property_string($numa_fmt, $data);
2091 $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
2092 $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
2ed5d572
AD
2093 return $res;
2094}
2095
040b06b7
DA
2096sub parse_hostpci {
2097 my ($value) = @_;
2098
2099 return undef if !$value;
2100
1f4f447b 2101 my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
0cea6a01 2102
1f4f447b
WB
2103 my @idlist = split(/;/, $res->{host});
2104 delete $res->{host};
2105 foreach my $id (@idlist) {
2106 if ($id =~ /^$PCIRE$/) {
a3139f90
WB
2107 if (defined($2)) {
2108 push @{$res->{pciid}}, { id => $1, function => $2 };
2109 } else {
b71351a7 2110 my $pcidevices = PVE::SysFSTools::lspci($1);
a3139f90
WB
2111 $res->{pciid} = $pcidevices->{$1};
2112 }
0cea6a01 2113 } else {
1f4f447b
WB
2114 # should have been caught by parse_property_string already
2115 die "failed to parse PCI id: $id\n";
0cea6a01 2116 }
040b06b7 2117 }
040b06b7
DA
2118 return $res;
2119}
2120
1e3baf05
DM
2121# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
2122sub parse_net {
2123 my ($data) = @_;
2124
cd9c34d1
WB
2125 my $res = eval { PVE::JSONSchema::parse_property_string($net_fmt, $data) };
2126 if ($@) {
2127 warn $@;
2128 return undef;
1e3baf05 2129 }
b5b99790
WB
2130 if (!defined($res->{macaddr})) {
2131 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
2132 $res->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
2133 }
0c9a7596
AD
2134 return $res;
2135}
2136
2137# ipconfigX ip=cidr,gw=ip,ip6=cidr,gw6=ip
2138sub parse_ipconfig {
2139 my ($data) = @_;
2140
2141 my $res = eval { PVE::JSONSchema::parse_property_string($ipconfig_fmt, $data) };
2142 if ($@) {
2143 warn $@;
2144 return undef;
2145 }
2146
2147 if ($res->{gw} && !$res->{ip}) {
2148 warn 'gateway specified without specifying an IP address';
2149 return undef;
2150 }
2151 if ($res->{gw6} && !$res->{ip6}) {
2152 warn 'IPv6 gateway specified without specifying an IPv6 address';
2153 return undef;
2154 }
2155 if ($res->{gw} && $res->{ip} eq 'dhcp') {
2156 warn 'gateway specified together with DHCP';
2157 return undef;
2158 }
2159 if ($res->{gw6} && $res->{ip6} !~ /^$IPV6RE/) {
2160 # gw6 + auto/dhcp
2161 warn "IPv6 gateway specified together with $res->{ip6} address";
2162 return undef;
2163 }
2164
2165 if (!$res->{ip} && !$res->{ip6}) {
2166 return { ip => 'dhcp', ip6 => 'dhcp' };
2167 }
2168
1e3baf05
DM
2169 return $res;
2170}
2171
2172sub print_net {
2173 my $net = shift;
2174
cd9c34d1 2175 return PVE::JSONSchema::print_property_string($net, $net_fmt);
1e3baf05
DM
2176}
2177
2178sub add_random_macs {
2179 my ($settings) = @_;
2180
2181 foreach my $opt (keys %$settings) {
2182 next if $opt !~ m/^net(\d+)$/;
2183 my $net = parse_net($settings->{$opt});
2184 next if !$net;
2185 $settings->{$opt} = print_net($net);
2186 }
2187}
2188
055d554d
DM
2189sub vm_is_volid_owner {
2190 my ($storecfg, $vmid, $volid) = @_;
2191
2192 if ($volid !~ m|^/|) {
2193 my ($path, $owner);
2194 eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
2195 if ($owner && ($owner == $vmid)) {
2196 return 1;
2197 }
2198 }
2199
2200 return undef;
2201}
2202
3dc38fbb
WB
2203sub split_flagged_list {
2204 my $text = shift || '';
2205 $text =~ s/[,;]/ /g;
2206 $text =~ s/^\s+//;
2207 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
2208}
2209
2210sub join_flagged_list {
2211 my ($how, $lst) = @_;
2212 join $how, map { $lst->{$_} . $_ } keys %$lst;
2213}
2214
055d554d 2215sub vmconfig_delete_pending_option {
3dc38fbb 2216 my ($conf, $key, $force) = @_;
055d554d
DM
2217
2218 delete $conf->{pending}->{$key};
3dc38fbb
WB
2219 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
2220 $pending_delete_hash->{$key} = $force ? '!' : '';
2221 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
2222}
2223
2224sub vmconfig_undelete_pending_option {
2225 my ($conf, $key) = @_;
2226
3dc38fbb 2227 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
055d554d
DM
2228 delete $pending_delete_hash->{$key};
2229
3dc38fbb
WB
2230 if (%$pending_delete_hash) {
2231 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
2232 } else {
2233 delete $conf->{pending}->{delete};
2234 }
2235}
2236
2237sub vmconfig_register_unused_drive {
2238 my ($storecfg, $vmid, $conf, $drive) = @_;
2239
2d9ddec5
WB
2240 if (drive_is_cloudinit($drive)) {
2241 eval { PVE::Storage::vdisk_free($storecfg, $drive->{file}) };
2242 warn $@ if $@;
2243 } elsif (!drive_is_cdrom($drive)) {
055d554d
DM
2244 my $volid = $drive->{file};
2245 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
8793d495 2246 PVE::QemuConfig->add_unused_volume($conf, $volid, $vmid);
055d554d
DM
2247 }
2248 }
2249}
2250
c750e90a
DM
2251sub vmconfig_cleanup_pending {
2252 my ($conf) = @_;
2253
2254 # remove pending changes when nothing changed
2255 my $changes;
2256 foreach my $opt (keys %{$conf->{pending}}) {
2257 if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq $conf->{$opt})) {
2258 $changes = 1;
2259 delete $conf->{pending}->{$opt};
2260 }
2261 }
2262
3dc38fbb 2263 my $current_delete_hash = split_flagged_list($conf->{pending}->{delete});
c750e90a 2264 my $pending_delete_hash = {};
3dc38fbb 2265 while (my ($opt, $force) = each %$current_delete_hash) {
c750e90a 2266 if (defined($conf->{$opt})) {
3dc38fbb 2267 $pending_delete_hash->{$opt} = $force;
c750e90a
DM
2268 } else {
2269 $changes = 1;
2270 }
2271 }
2272
3dc38fbb
WB
2273 if (%$pending_delete_hash) {
2274 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
c750e90a
DM
2275 } else {
2276 delete $conf->{pending}->{delete};
2277 }
2278
2279 return $changes;
2280}
2281
bd27e851 2282# smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
ff6ffe20 2283my $smbios1_fmt = {
bd27e851
WB
2284 uuid => {
2285 type => 'string',
2286 pattern => '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
2287 format_description => 'UUID',
52261945 2288 description => "Set SMBIOS1 UUID.",
bd27e851
WB
2289 optional => 1,
2290 },
2291 version => {
2292 type => 'string',
2293 pattern => '\S+',
7f694a71 2294 format_description => 'string',
52261945 2295 description => "Set SMBIOS1 version.",
bd27e851
WB
2296 optional => 1,
2297 },
2298 serial => {
2299 type => 'string',
2300 pattern => '\S+',
7f694a71 2301 format_description => 'string',
52261945 2302 description => "Set SMBIOS1 serial number.",
bd27e851
WB
2303 optional => 1,
2304 },
2305 manufacturer => {
2306 type => 'string',
2307 pattern => '\S+',
7f694a71 2308 format_description => 'string',
52261945 2309 description => "Set SMBIOS1 manufacturer.",
bd27e851
WB
2310 optional => 1,
2311 },
2312 product => {
2313 type => 'string',
2314 pattern => '\S+',
7f694a71 2315 format_description => 'string',
52261945 2316 description => "Set SMBIOS1 product ID.",
bd27e851
WB
2317 optional => 1,
2318 },
2319 sku => {
2320 type => 'string',
2321 pattern => '\S+',
7f694a71 2322 format_description => 'string',
52261945 2323 description => "Set SMBIOS1 SKU string.",
bd27e851
WB
2324 optional => 1,
2325 },
2326 family => {
2327 type => 'string',
2328 pattern => '\S+',
7f694a71 2329 format_description => 'string',
52261945 2330 description => "Set SMBIOS1 family string.",
bd27e851
WB
2331 optional => 1,
2332 },
2796e7d5
DM
2333};
2334
2796e7d5
DM
2335sub parse_smbios1 {
2336 my ($data) = @_;
2337
ff6ffe20 2338 my $res = eval { PVE::JSONSchema::parse_property_string($smbios1_fmt, $data) };
bd27e851 2339 warn $@ if $@;
2796e7d5
DM
2340 return $res;
2341}
2342
cd11416f
DM
2343sub print_smbios1 {
2344 my ($smbios1) = @_;
ff6ffe20 2345 return PVE::JSONSchema::print_property_string($smbios1, $smbios1_fmt);
cd11416f
DM
2346}
2347
ff6ffe20 2348PVE::JSONSchema::register_format('pve-qm-smbios1', $smbios1_fmt);
2796e7d5 2349
1e3baf05
DM
2350PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
2351sub verify_bootdisk {
2352 my ($value, $noerr) = @_;
2353
74479ee9 2354 return $value if is_valid_drivename($value);
1e3baf05
DM
2355
2356 return undef if $noerr;
2357
2358 die "invalid boot disk '$value'\n";
2359}
2360
0ea9541d
DM
2361sub parse_watchdog {
2362 my ($value) = @_;
2363
2364 return undef if !$value;
2365
ec3582b5
WB
2366 my $res = eval { PVE::JSONSchema::parse_property_string($watchdog_fmt, $value) };
2367 warn $@ if $@;
0ea9541d
DM
2368 return $res;
2369}
2370
9d66b397
SI
2371sub parse_guest_agent {
2372 my ($value) = @_;
2373
2374 return {} if !defined($value->{agent});
2375
2376 my $res = eval { PVE::JSONSchema::parse_property_string($agent_fmt, $value->{agent}) };
2377 warn $@ if $@;
2378
2379 # if the agent is disabled ignore the other potentially set properties
2380 return {} if !$res->{enabled};
2381 return $res;
2382}
2383
55655ebc
DC
2384sub parse_vga {
2385 my ($value) = @_;
2386
2387 return {} if !$value;
2388 my $res = eval { PVE::JSONSchema::parse_property_string($vga_fmt, $value) };
2389 warn $@ if $@;
2390 return $res;
2391}
2392
1e3baf05
DM
2393PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
2394sub verify_usb_device {
2395 my ($value, $noerr) = @_;
2396
2397 return $value if parse_usb_device($value);
2398
2399 return undef if $noerr;
19672434 2400
1e3baf05
DM
2401 die "unable to parse usb device\n";
2402}
2403
1e3baf05
DM
2404# add JSON properties for create and set function
2405sub json_config_properties {
2406 my $prop = shift;
2407
2408 foreach my $opt (keys %$confdesc) {
c6737ef1 2409 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' || $opt eq 'runningmachine';
1e3baf05
DM
2410 $prop->{$opt} = $confdesc->{$opt};
2411 }
2412
2413 return $prop;
2414}
2415
d41121fd
DM
2416# return copy of $confdesc_cloudinit to generate documentation
2417sub cloudinit_config_properties {
2418
2419 return dclone($confdesc_cloudinit);
2420}
2421
1e3baf05
DM
2422sub check_type {
2423 my ($key, $value) = @_;
2424
2425 die "unknown setting '$key'\n" if !$confdesc->{$key};
2426
2427 my $type = $confdesc->{$key}->{type};
2428
6b64503e 2429 if (!defined($value)) {
1e3baf05
DM
2430 die "got undefined value\n";
2431 }
2432
2433 if ($value =~ m/[\n\r]/) {
2434 die "property contains a line feed\n";
2435 }
2436
2437 if ($type eq 'boolean') {
19672434
DM
2438 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2439 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2440 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
2441 } elsif ($type eq 'integer') {
2442 return int($1) if $value =~ m/^(\d+)$/;
2443 die "type check ('integer') failed - got '$value'\n";
04432191
AD
2444 } elsif ($type eq 'number') {
2445 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2446 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
2447 } elsif ($type eq 'string') {
2448 if (my $fmt = $confdesc->{$key}->{format}) {
1e3baf05 2449 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
2450 return $value;
2451 }
1e3baf05 2452 $value =~ s/^\"(.*)\"$/$1/;
19672434 2453 return $value;
1e3baf05
DM
2454 } else {
2455 die "internal error"
2456 }
2457}
2458
1e3baf05
DM
2459sub touch_config {
2460 my ($vmid) = @_;
2461
ffda963f 2462 my $conf = PVE::QemuConfig->config_file($vmid);
1e3baf05
DM
2463 utime undef, undef, $conf;
2464}
2465
1e3baf05 2466sub destroy_vm {
15cc8784 2467 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1e3baf05 2468
ffda963f 2469 my $conffile = PVE::QemuConfig->config_file($vmid);
1e3baf05 2470
ffda963f 2471 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 2472
ffda963f 2473 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 2474
5e67a2d2
DC
2475 if ($conf->{template}) {
2476 # check if any base image is still used by a linked clone
2477 foreach_drive($conf, sub {
2478 my ($ds, $drive) = @_;
2479
2480 return if drive_is_cdrom($drive);
2481
2482 my $volid = $drive->{file};
2483
2484 return if !$volid || $volid =~ m|^/|;
2485
2486 die "base volume '$volid' is still in use by linked cloned\n"
2487 if PVE::Storage::volume_is_base_and_used($storecfg, $volid);
2488
2489 });
2490 }
2491
19672434 2492 # only remove disks owned by this VM
1e3baf05
DM
2493 foreach_drive($conf, sub {
2494 my ($ds, $drive) = @_;
2495
9c52f5ed 2496 return if drive_is_cdrom($drive, 1);
1e3baf05
DM
2497
2498 my $volid = $drive->{file};
ed221350 2499
ff1a2432 2500 return if !$volid || $volid =~ m|^/|;
1e3baf05 2501
6b64503e 2502 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 2503 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 2504
31b52247
FG
2505 eval {
2506 PVE::Storage::vdisk_free($storecfg, $volid);
2507 };
2508 warn "Could not remove disk '$volid', check manually: $@" if $@;
2509
1e3baf05 2510 });
19672434 2511
a6af7b3e 2512 if ($keep_empty_config) {
9c502e26 2513 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
2514 } else {
2515 unlink $conffile;
2516 }
1e3baf05
DM
2517
2518 # also remove unused disk
2519 eval {
6b64503e 2520 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
2521
2522 eval {
6b64503e 2523 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 2524 my ($volid, $sid, $volname, $d) = @_;
6b64503e 2525 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
2526 });
2527 };
2528 warn $@ if $@;
2529
2530 };
2531 warn $@ if $@;
2532}
2533
1e3baf05
DM
2534sub parse_vm_config {
2535 my ($filename, $raw) = @_;
2536
2537 return undef if !defined($raw);
2538
554ac7e7 2539 my $res = {
fc1ddcdc 2540 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 2541 snapshots => {},
0d732d16 2542 pending => {},
554ac7e7 2543 };
1e3baf05 2544
19672434 2545 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
2546 || die "got strange filename '$filename'";
2547
2548 my $vmid = $1;
2549
0d18dcfc 2550 my $conf = $res;
b0ec896e 2551 my $descr;
e297c490 2552 my $section = '';
0581fe4f 2553
0d18dcfc
DM
2554 my @lines = split(/\n/, $raw);
2555 foreach my $line (@lines) {
1e3baf05 2556 next if $line =~ m/^\s*$/;
be190583 2557
eab09f4e 2558 if ($line =~ m/^\[PENDING\]\s*$/i) {
e297c490 2559 $section = 'pending';
b0ec896e
DM
2560 if (defined($descr)) {
2561 $descr =~ s/\s+$//;
2562 $conf->{description} = $descr;
2563 }
2564 $descr = undef;
e297c490 2565 $conf = $res->{$section} = {};
eab09f4e
AD
2566 next;
2567
0d732d16 2568 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
e297c490 2569 $section = $1;
b0ec896e
DM
2570 if (defined($descr)) {
2571 $descr =~ s/\s+$//;
2572 $conf->{description} = $descr;
2573 }
2574 $descr = undef;
e297c490 2575 $conf = $res->{snapshots}->{$section} = {};
0d18dcfc
DM
2576 next;
2577 }
1e3baf05 2578
0581fe4f 2579 if ($line =~ m/^\#(.*)\s*$/) {
b0ec896e 2580 $descr = '' if !defined($descr);
0581fe4f
DM
2581 $descr .= PVE::Tools::decode_text($1) . "\n";
2582 next;
2583 }
2584
1e3baf05 2585 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
b0ec896e 2586 $descr = '' if !defined($descr);
0581fe4f 2587 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
2588 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2589 $conf->{snapstate} = $1;
1e3baf05
DM
2590 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2591 my $key = $1;
2592 my $value = $2;
0d18dcfc 2593 $conf->{$key} = $value;
ef824322 2594 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
e297c490 2595 my $value = $1;
ef824322
DM
2596 if ($section eq 'pending') {
2597 $conf->{delete} = $value; # we parse this later
2598 } else {
2599 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
eab09f4e 2600 }
15cf7698 2601 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(.+?)\s*$/) {
1e3baf05
DM
2602 my $key = $1;
2603 my $value = $2;
2604 eval { $value = check_type($key, $value); };
2605 if ($@) {
2606 warn "vm $vmid - unable to parse value of '$key' - $@";
2607 } else {
b799312f 2608 $key = 'ide2' if $key eq 'cdrom';
1e3baf05 2609 my $fmt = $confdesc->{$key}->{format};
b799312f 2610 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
1e3baf05
DM
2611 my $v = parse_drive($key, $value);
2612 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
2613 $v->{file} = $volid;
6b64503e 2614 $value = print_drive($vmid, $v);
1e3baf05
DM
2615 } else {
2616 warn "vm $vmid - unable to parse value of '$key'\n";
2617 next;
2618 }
2619 }
2620
b799312f 2621 $conf->{$key} = $value;
1e3baf05
DM
2622 }
2623 }
2624 }
2625
b0ec896e
DM
2626 if (defined($descr)) {
2627 $descr =~ s/\s+$//;
2628 $conf->{description} = $descr;
2629 }
0d18dcfc 2630 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
2631
2632 return $res;
2633}
2634
1858638f
DM
2635sub write_vm_config {
2636 my ($filename, $conf) = @_;
1e3baf05 2637
0d18dcfc
DM
2638 delete $conf->{snapstate}; # just to be sure
2639
1858638f
DM
2640 if ($conf->{cdrom}) {
2641 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
2642 $conf->{ide2} = $conf->{cdrom};
2643 delete $conf->{cdrom};
2644 }
1e3baf05
DM
2645
2646 # we do not use 'smp' any longer
1858638f
DM
2647 if ($conf->{sockets}) {
2648 delete $conf->{smp};
2649 } elsif ($conf->{smp}) {
2650 $conf->{sockets} = $conf->{smp};
2651 delete $conf->{cores};
2652 delete $conf->{smp};
1e3baf05
DM
2653 }
2654
ee2f90b1 2655 my $used_volids = {};
0d18dcfc 2656
ee2f90b1 2657 my $cleanup_config = sub {
ef824322 2658 my ($cref, $pending, $snapname) = @_;
1858638f 2659
ee2f90b1
DM
2660 foreach my $key (keys %$cref) {
2661 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
ef824322 2662 $key eq 'snapstate' || $key eq 'pending';
ee2f90b1 2663 my $value = $cref->{$key};
ef824322
DM
2664 if ($key eq 'delete') {
2665 die "propertry 'delete' is only allowed in [PENDING]\n"
2666 if !$pending;
2667 # fixme: check syntax?
2668 next;
2669 }
ee2f90b1
DM
2670 eval { $value = check_type($key, $value); };
2671 die "unable to parse value of '$key' - $@" if $@;
1858638f 2672
ee2f90b1
DM
2673 $cref->{$key} = $value;
2674
74479ee9 2675 if (!$snapname && is_valid_drivename($key)) {
ed221350 2676 my $drive = parse_drive($key, $value);
ee2f90b1
DM
2677 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
2678 }
1e3baf05 2679 }
ee2f90b1
DM
2680 };
2681
2682 &$cleanup_config($conf);
ef824322
DM
2683
2684 &$cleanup_config($conf->{pending}, 1);
2685
ee2f90b1 2686 foreach my $snapname (keys %{$conf->{snapshots}}) {
ef824322
DM
2687 die "internal error" if $snapname eq 'pending';
2688 &$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
1e3baf05
DM
2689 }
2690
1858638f
DM
2691 # remove 'unusedX' settings if we re-add a volume
2692 foreach my $key (keys %$conf) {
2693 my $value = $conf->{$key};
ee2f90b1 2694 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 2695 delete $conf->{$key};
1e3baf05 2696 }
1858638f 2697 }
be190583 2698
0d18dcfc 2699 my $generate_raw_config = sub {
b0ec896e 2700 my ($conf, $pending) = @_;
0581fe4f 2701
0d18dcfc
DM
2702 my $raw = '';
2703
2704 # add description as comment to top of file
b0ec896e
DM
2705 if (defined(my $descr = $conf->{description})) {
2706 if ($descr) {
2707 foreach my $cl (split(/\n/, $descr)) {
2708 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
2709 }
2710 } else {
2711 $raw .= "#\n" if $pending;
2712 }
0d18dcfc
DM
2713 }
2714
2715 foreach my $key (sort keys %$conf) {
ef824322 2716 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
0d18dcfc
DM
2717 $raw .= "$key: $conf->{$key}\n";
2718 }
2719 return $raw;
2720 };
0581fe4f 2721
0d18dcfc 2722 my $raw = &$generate_raw_config($conf);
ef824322
DM
2723
2724 if (scalar(keys %{$conf->{pending}})){
2725 $raw .= "\n[PENDING]\n";
b0ec896e 2726 $raw .= &$generate_raw_config($conf->{pending}, 1);
ef824322
DM
2727 }
2728
0d18dcfc
DM
2729 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
2730 $raw .= "\n[$snapname]\n";
2731 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 2732 }
1e3baf05 2733
1858638f
DM
2734 return $raw;
2735}
1e3baf05 2736
19672434 2737sub load_defaults {
1e3baf05
DM
2738
2739 my $res = {};
2740
2741 # we use static defaults from our JSON schema configuration
2742 foreach my $key (keys %$confdesc) {
2743 if (defined(my $default = $confdesc->{$key}->{default})) {
2744 $res->{$key} = $default;
2745 }
2746 }
19672434 2747
1e3baf05
DM
2748 return $res;
2749}
2750
2751sub config_list {
2752 my $vmlist = PVE::Cluster::get_vmlist();
2753 my $res = {};
2754 return $res if !$vmlist || !$vmlist->{ids};
2755 my $ids = $vmlist->{ids};
2756
1e3baf05
DM
2757 foreach my $vmid (keys %$ids) {
2758 my $d = $ids->{$vmid};
2759 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 2760 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
2761 $res->{$vmid}->{exists} = 1;
2762 }
2763 return $res;
2764}
2765
64e13401
DM
2766# test if VM uses local resources (to prevent migration)
2767sub check_local_resources {
2768 my ($conf, $noerr) = @_;
2769
2770 my $loc_res = 0;
19672434 2771
e0ab7331
DM
2772 $loc_res = 1 if $conf->{hostusb}; # old syntax
2773 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 2774
0d29ab3b 2775 foreach my $k (keys %$conf) {
49ca581d 2776 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
d44712fc
EK
2777 # sockets are safe: they will recreated be on the target side post-migrate
2778 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2fe1a152 2779 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
2780 }
2781
2782 die "VM uses local resources\n" if $loc_res && !$noerr;
2783
2784 return $loc_res;
2785}
2786
719893a9 2787# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
2788sub check_storage_availability {
2789 my ($storecfg, $conf, $node) = @_;
2790
2791 foreach_drive($conf, sub {
2792 my ($ds, $drive) = @_;
2793
2794 my $volid = $drive->{file};
2795 return if !$volid;
2796
2797 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2798 return if !$sid;
2799
2800 # check if storage is available on both nodes
2801 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
2802 PVE::Storage::storage_check_node($storecfg, $sid, $node);
2803 });
2804}
2805
719893a9
DM
2806# list nodes where all VM images are available (used by has_feature API)
2807sub shared_nodes {
2808 my ($conf, $storecfg) = @_;
2809
2810 my $nodelist = PVE::Cluster::get_nodelist();
2811 my $nodehash = { map { $_ => 1 } @$nodelist };
2812 my $nodename = PVE::INotify::nodename();
be190583 2813
719893a9
DM
2814 foreach_drive($conf, sub {
2815 my ($ds, $drive) = @_;
2816
2817 my $volid = $drive->{file};
2818 return if !$volid;
2819
2820 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2821 if ($storeid) {
2822 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
2823 if ($scfg->{disable}) {
2824 $nodehash = {};
2825 } elsif (my $avail = $scfg->{nodes}) {
2826 foreach my $node (keys %$nodehash) {
2827 delete $nodehash->{$node} if !$avail->{$node};
2828 }
2829 } elsif (!$scfg->{shared}) {
2830 foreach my $node (keys %$nodehash) {
2831 delete $nodehash->{$node} if $node ne $nodename
2832 }
2833 }
2834 }
2835 });
2836
2837 return $nodehash
2838}
2839
1e3baf05
DM
2840sub check_cmdline {
2841 my ($pidfile, $pid) = @_;
2842
6b64503e
DM
2843 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
2844 if (defined($fh)) {
1e3baf05
DM
2845 my $line = <$fh>;
2846 $fh->close;
2847 return undef if !$line;
6b64503e 2848 my @param = split(/\0/, $line);
1e3baf05
DM
2849
2850 my $cmd = $param[0];
6908fd9b 2851 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m@(?:^|/)qemu-system-[^/]+$@);
1e3baf05
DM
2852
2853 for (my $i = 0; $i < scalar (@param); $i++) {
2854 my $p = $param[$i];
2855 next if !$p;
2856 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2857 my $p = $param[$i+1];
2858 return 1 if $p && ($p eq $pidfile);
2859 return undef;
2860 }
2861 }
2862 }
2863 return undef;
2864}
2865
2866sub check_running {
7e8dcf2c 2867 my ($vmid, $nocheck, $node) = @_;
1e3baf05 2868
ffda963f 2869 my $filename = PVE::QemuConfig->config_file($vmid, $node);
1e3baf05
DM
2870
2871 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 2872 if !$nocheck && ! -f $filename;
1e3baf05 2873
e6c3b671 2874 my $pidfile = pidfile_name($vmid);
1e3baf05 2875
e6c3b671
DM
2876 if (my $fd = IO::File->new("<$pidfile")) {
2877 my $st = stat($fd);
1e3baf05 2878 my $line = <$fd>;
6b64503e 2879 close($fd);
1e3baf05
DM
2880
2881 my $mtime = $st->mtime;
2882 if ($mtime > time()) {
2883 warn "file '$filename' modified in future\n";
2884 }
2885
2886 if ($line =~ m/^(\d+)$/) {
2887 my $pid = $1;
e6c3b671
DM
2888 if (check_cmdline($pidfile, $pid)) {
2889 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
2890 return $pid;
2891 }
2892 }
1e3baf05
DM
2893 }
2894 }
2895
2896 return undef;
2897}
2898
2899sub vzlist {
19672434 2900
1e3baf05
DM
2901 my $vzlist = config_list();
2902
6b64503e 2903 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 2904
19672434 2905 while (defined(my $de = $fd->read)) {
1e3baf05
DM
2906 next if $de !~ m/^(\d+)\.pid$/;
2907 my $vmid = $1;
6b64503e
DM
2908 next if !defined($vzlist->{$vmid});
2909 if (my $pid = check_running($vmid)) {
1e3baf05
DM
2910 $vzlist->{$vmid}->{pid} = $pid;
2911 }
2912 }
2913
2914 return $vzlist;
2915}
2916
1e3baf05
DM
2917sub disksize {
2918 my ($storecfg, $conf) = @_;
2919
2920 my $bootdisk = $conf->{bootdisk};
2921 return undef if !$bootdisk;
74479ee9 2922 return undef if !is_valid_drivename($bootdisk);
1e3baf05
DM
2923
2924 return undef if !$conf->{$bootdisk};
2925
2926 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
2927 return undef if !defined($drive);
2928
2929 return undef if drive_is_cdrom($drive);
2930
2931 my $volid = $drive->{file};
2932 return undef if !$volid;
2933
24afaca0 2934 return $drive->{size};
1e3baf05
DM
2935}
2936
b1a70cab
DM
2937our $vmstatus_return_properties = {
2938 vmid => get_standard_option('pve-vmid'),
2939 status => {
2940 description => "Qemu process status.",
2941 type => 'string',
2942 enum => ['stopped', 'running'],
2943 },
2944 maxmem => {
2945 description => "Maximum memory in bytes.",
2946 type => 'integer',
2947 optional => 1,
2948 renderer => 'bytes',
2949 },
2950 maxdisk => {
2951 description => "Root disk size in bytes.",
2952 type => 'integer',
2953 optional => 1,
2954 renderer => 'bytes',
2955 },
2956 name => {
2957 description => "VM name.",
2958 type => 'string',
2959 optional => 1,
2960 },
2961 qmpstatus => {
2962 description => "Qemu QMP agent status.",
2963 type => 'string',
2964 optional => 1,
2965 },
2966 pid => {
2967 description => "PID of running qemu process.",
2968 type => 'integer',
2969 optional => 1,
2970 },
2971 uptime => {
2972 description => "Uptime.",
2973 type => 'integer',
2974 optional => 1,
2975 renderer => 'duration',
2976 },
2977 cpus => {
2978 description => "Maximum usable CPUs.",
2979 type => 'number',
2980 optional => 1,
2981 },
2982};
2983
1e3baf05
DM
2984my $last_proc_pid_stat;
2985
03a33f30
DM
2986# get VM status information
2987# This must be fast and should not block ($full == false)
2988# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2989sub vmstatus {
03a33f30 2990 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2991
2992 my $res = {};
2993
19672434 2994 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2995
2996 my $list = vzlist();
3618ee99
EK
2997 my $defaults = load_defaults();
2998
694fcad4 2999 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 3000
ae4915a2
DM
3001 my $cpucount = $cpuinfo->{cpus} || 1;
3002
1e3baf05
DM
3003 foreach my $vmid (keys %$list) {
3004 next if $opt_vmid && ($vmid ne $opt_vmid);
3005
ffda963f 3006 my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
1e3baf05
DM
3007 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
3008
b1a70cab 3009 my $d = { vmid => $vmid };
1e3baf05
DM
3010 $d->{pid} = $list->{$vmid}->{pid};
3011
3012 # fixme: better status?
3013 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
3014
af990afe
DM
3015 my $size = disksize($storecfg, $conf);
3016 if (defined($size)) {
3017 $d->{disk} = 0; # no info available
1e3baf05
DM
3018 $d->{maxdisk} = $size;
3019 } else {
3020 $d->{disk} = 0;
3021 $d->{maxdisk} = 0;
3022 }
3023
3618ee99
EK
3024 $d->{cpus} = ($conf->{sockets} || $defaults->{sockets})
3025 * ($conf->{cores} || $defaults->{cores});
ae4915a2 3026 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
d7c8364b 3027 $d->{cpus} = $conf->{vcpus} if $conf->{vcpus};
ae4915a2 3028
1e3baf05 3029 $d->{name} = $conf->{name} || "VM $vmid";
3618ee99
EK
3030 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024)
3031 : $defaults->{memory}*(1024*1024);
1e3baf05 3032
8b1accf7 3033 if ($conf->{balloon}) {
4bdb0514 3034 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
3618ee99
EK
3035 $d->{shares} = defined($conf->{shares}) ? $conf->{shares}
3036 : $defaults->{shares};
8b1accf7
DM
3037 }
3038
1e3baf05
DM
3039 $d->{uptime} = 0;
3040 $d->{cpu} = 0;
1e3baf05
DM
3041 $d->{mem} = 0;
3042
3043 $d->{netout} = 0;
3044 $d->{netin} = 0;
3045
3046 $d->{diskread} = 0;
3047 $d->{diskwrite} = 0;
3048
ffda963f 3049 $d->{template} = PVE::QemuConfig->is_template($conf);
4d8c851b 3050
8107b378
DC
3051 $d->{serial} = 1 if conf_has_serial($conf);
3052
1e3baf05
DM
3053 $res->{$vmid} = $d;
3054 }
3055
3056 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
3057 foreach my $dev (keys %$netdev) {
3058 next if $dev !~ m/^tap([1-9]\d*)i/;
3059 my $vmid = $1;
3060 my $d = $res->{$vmid};
3061 next if !$d;
19672434 3062
1e3baf05
DM
3063 $d->{netout} += $netdev->{$dev}->{receive};
3064 $d->{netin} += $netdev->{$dev}->{transmit};
604ea644
AD
3065
3066 if ($full) {
3067 $d->{nics}->{$dev}->{netout} = $netdev->{$dev}->{receive};
3068 $d->{nics}->{$dev}->{netin} = $netdev->{$dev}->{transmit};
3069 }
3070
1e3baf05
DM
3071 }
3072
1e3baf05
DM
3073 my $ctime = gettimeofday;
3074
3075 foreach my $vmid (keys %$list) {
3076
3077 my $d = $res->{$vmid};
3078 my $pid = $d->{pid};
3079 next if !$pid;
3080
694fcad4
DM
3081 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
3082 next if !$pstat; # not running
19672434 3083
694fcad4 3084 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 3085
694fcad4 3086 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 3087
694fcad4 3088 if ($pstat->{vsize}) {
6b64503e 3089 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
3090 }
3091
3092 my $old = $last_proc_pid_stat->{$pid};
3093 if (!$old) {
19672434
DM
3094 $last_proc_pid_stat->{$pid} = {
3095 time => $ctime,
1e3baf05
DM
3096 used => $used,
3097 cpu => 0,
1e3baf05
DM
3098 };
3099 next;
3100 }
3101
7f0b5beb 3102 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
3103
3104 if ($dtime > 1000) {
3105 my $dutime = $used - $old->{used};
3106
ae4915a2 3107 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 3108 $last_proc_pid_stat->{$pid} = {
19672434 3109 time => $ctime,
1e3baf05
DM
3110 used => $used,
3111 cpu => $d->{cpu},
1e3baf05
DM
3112 };
3113 } else {
3114 $d->{cpu} = $old->{cpu};
1e3baf05
DM
3115 }
3116 }
3117
f5eb281a 3118 return $res if !$full;
03a33f30
DM
3119
3120 my $qmpclient = PVE::QMPClient->new();
3121
64e7fcf2
DM
3122 my $ballooncb = sub {
3123 my ($vmid, $resp) = @_;
3124
3125 my $info = $resp->{'return'};
38babf81
DM
3126 return if !$info->{max_mem};
3127
64e7fcf2
DM
3128 my $d = $res->{$vmid};
3129
38babf81
DM
3130 # use memory assigned to VM
3131 $d->{maxmem} = $info->{max_mem};
3132 $d->{balloon} = $info->{actual};
3133
3134 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
3135 $d->{mem} = $info->{total_mem} - $info->{free_mem};
3136 $d->{freemem} = $info->{free_mem};
64e7fcf2
DM
3137 }
3138
604ea644 3139 $d->{ballooninfo} = $info;
64e7fcf2
DM
3140 };
3141
03a33f30
DM
3142 my $blockstatscb = sub {
3143 my ($vmid, $resp) = @_;
3144 my $data = $resp->{'return'} || [];
3145 my $totalrdbytes = 0;
3146 my $totalwrbytes = 0;
604ea644 3147
03a33f30
DM
3148 for my $blockstat (@$data) {
3149 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
3150 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
604ea644
AD
3151
3152 $blockstat->{device} =~ s/drive-//;
3153 $res->{$vmid}->{blockstat}->{$blockstat->{device}} = $blockstat->{stats};
03a33f30
DM
3154 }
3155 $res->{$vmid}->{diskread} = $totalrdbytes;
3156 $res->{$vmid}->{diskwrite} = $totalwrbytes;
3157 };
3158
3159 my $statuscb = sub {
3160 my ($vmid, $resp) = @_;
64e7fcf2 3161
03a33f30 3162 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
3163 # this fails if ballon driver is not loaded, so this must be
3164 # the last commnand (following command are aborted if this fails).
38babf81 3165 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
3166
3167 my $status = 'unknown';
3168 if (!defined($status = $resp->{'return'}->{status})) {
3169 warn "unable to get VM status\n";
3170 return;
3171 }
3172
3173 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
3174 };
3175
3176 foreach my $vmid (keys %$list) {
3177 next if $opt_vmid && ($vmid ne $opt_vmid);
3178 next if !$res->{$vmid}->{pid}; # not running
3179 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
3180 }
3181
b017fbda 3182 $qmpclient->queue_execute(undef, 2);
03a33f30
DM
3183
3184 foreach my $vmid (keys %$list) {
3185 next if $opt_vmid && ($vmid ne $opt_vmid);
3186 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
3187 }
3188
1e3baf05
DM
3189 return $res;
3190}
3191
3192sub foreach_drive {
b74ff047 3193 my ($conf, $func, @param) = @_;
1e3baf05 3194
74479ee9
FG
3195 foreach my $ds (valid_drive_names()) {
3196 next if !defined($conf->{$ds});
1e3baf05 3197
6b64503e 3198 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
3199 next if !$drive;
3200
b74ff047 3201 &$func($ds, $drive, @param);
1e3baf05
DM
3202 }
3203}
3204
d5769dc2 3205sub foreach_volid {
b6adff33 3206 my ($conf, $func, @param) = @_;
be190583 3207
d5769dc2
DM
3208 my $volhash = {};
3209
3210 my $test_volid = sub {
ec82e3ee 3211 my ($volid, $is_cdrom, $replicate, $shared, $snapname) = @_;
d5769dc2
DM
3212
3213 return if !$volid;
be190583 3214
392f8b5d
DM
3215 $volhash->{$volid}->{cdrom} //= 1;
3216 $volhash->{$volid}->{cdrom} = 0 if !$is_cdrom;
3217
3218 $volhash->{$volid}->{replicate} //= 0;
3219 $volhash->{$volid}->{replicate} = 1 if $replicate;
39019f75 3220
ec82e3ee
CH
3221 $volhash->{$volid}->{shared} //= 0;
3222 $volhash->{$volid}->{shared} = 1 if $shared;
3223
39019f75
DM
3224 $volhash->{$volid}->{referenced_in_config} //= 0;
3225 $volhash->{$volid}->{referenced_in_config} = 1 if !defined($snapname);
3226
3227 $volhash->{$volid}->{referenced_in_snapshot}->{$snapname} = 1
3228 if defined($snapname);
d5769dc2
DM
3229 };
3230
ed221350 3231 foreach_drive($conf, sub {
d5769dc2 3232 my ($ds, $drive) = @_;
ec82e3ee 3233 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, undef);
d5769dc2
DM
3234 });
3235
3236 foreach my $snapname (keys %{$conf->{snapshots}}) {
3237 my $snap = $conf->{snapshots}->{$snapname};
39019f75 3238 $test_volid->($snap->{vmstate}, 0, 1, $snapname);
ed221350 3239 foreach_drive($snap, sub {
d5769dc2 3240 my ($ds, $drive) = @_;
ec82e3ee 3241 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, $snapname);
d5769dc2
DM
3242 });
3243 }
3244
3245 foreach my $volid (keys %$volhash) {
b6adff33 3246 &$func($volid, $volhash->{$volid}, @param);
d5769dc2
DM
3247 }
3248}
3249
8107b378
DC
3250sub conf_has_serial {
3251 my ($conf) = @_;
3252
3253 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3254 if ($conf->{"serial$i"}) {
3255 return 1;
3256 }
3257 }
3258
3259 return 0;
3260}
3261
86b8228b
DM
3262sub vga_conf_has_spice {
3263 my ($vga) = @_;
3264
55655ebc
DC
3265 my $vgaconf = parse_vga($vga);
3266 my $vgatype = $vgaconf->{type};
3267 return 0 if !$vgatype || $vgatype !~ m/^qxl([234])?$/;
590e698c
DM
3268
3269 return $1 || 1;
86b8228b
DM
3270}
3271
d731ecbe
WB
3272my $host_arch; # FIXME: fix PVE::Tools::get_host_arch
3273sub get_host_arch() {
3274 $host_arch = (POSIX::uname())[4] if !$host_arch;
3275 return $host_arch;
3276}
3277
3278sub is_native($) {
3279 my ($arch) = @_;
3280 return get_host_arch() eq $arch;
3281}
3282
3283my $default_machines = {
3284 x86_64 => 'pc',
3285 aarch64 => 'virt',
3286};
3287
3288sub get_basic_machine_info {
3289 my ($conf, $forcemachine) = @_;
3290
3291 my $arch = $conf->{arch} // get_host_arch();
3292 my $machine = $forcemachine || $conf->{machine} || $default_machines->{$arch};
3293 return ($arch, $machine);
3294}
3295
96ed3574
WB
3296sub get_ovmf_files($) {
3297 my ($arch) = @_;
3298
3299 my $ovmf = $OVMF->{$arch}
3300 or die "no OVMF images known for architecture '$arch'\n";
3301
3302 return @$ovmf;
3303}
3304
6908fd9b
WB
3305my $Arch2Qemu = {
3306 aarch64 => '/usr/bin/qemu-system-aarch64',
3307 x86_64 => '/usr/bin/qemu-system-x86_64',
3308};
3309sub get_command_for_arch($) {
3310 my ($arch) = @_;
3311 return '/usr/bin/kvm' if is_native($arch);
3312
3313 my $cmd = $Arch2Qemu->{$arch}
3314 or die "don't know how to emulate architecture '$arch'\n";
3315 return $cmd;
3316}
3317
4fc262bd
WB
3318sub get_cpu_options {
3319 my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough) = @_;
3320
3321 my $cpuFlags = [];
3322 my $ostype = $conf->{ostype};
3323
3324 my $cpu = $kvm ? "kvm64" : "qemu64";
0f27a91d
WB
3325 if ($arch eq 'aarch64') {
3326 $cpu = 'cortex-a57';
3327 }
4fc262bd
WB
3328 if (my $cputype = $conf->{cpu}) {
3329 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
3330 or die "Cannot parse cpu description: $cputype\n";
3331 $cpu = $cpuconf->{cputype};
3332 $kvm_off = 1 if $cpuconf->{hidden};
3333
3334 if (defined(my $flags = $cpuconf->{flags})) {
3335 push @$cpuFlags, split(";", $flags);
3336 }
3337 }
3338
1ea63c15 3339 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64' && $arch eq 'x86_64';
4fc262bd
WB
3340
3341 push @$cpuFlags , '-x2apic'
3342 if $conf->{ostype} && $conf->{ostype} eq 'solaris';
3343
3344 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3345
3346 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3347
1ea63c15 3348 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3) && $arch eq 'x86_64') {
4fc262bd
WB
3349
3350 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3351 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3352 }
3353
3354 add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough) if $kvm;
3355
1ea63c15 3356 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
4fc262bd
WB
3357
3358 push @$cpuFlags, 'kvm=off' if $kvm_off;
3359
3360 if (my $cpu_vendor = $cpu_vendor_list->{$cpu}) {
3361 push @$cpuFlags, "vendor=${cpu_vendor}"
3362 if $cpu_vendor ne 'default';
3363 } elsif ($arch ne 'aarch64') {
3364 die "internal error"; # should not happen
3365 }
3366
3367 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3368
3369 return ('-cpu', $cpu);
3370}
3371
1e3baf05 3372sub config_to_command {
67812f9c 3373 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
3374
3375 my $cmd = [];
8c559505
DM
3376 my $globalFlags = [];
3377 my $machineFlags = [];
3378 my $rtcFlags = [];
5bdcf937 3379 my $devices = [];
b78ebef7 3380 my $pciaddr = '';
5bdcf937 3381 my $bridges = {};
1e3baf05
DM
3382 my $kvmver = kvm_user_version();
3383 my $vernum = 0; # unknown
b42d3cf9 3384 my $ostype = $conf->{ostype};
4317f69f 3385 my $winversion = windows_version($ostype);
d731ecbe
WB
3386 my $kvm = $conf->{kvm};
3387
3388 my ($arch, $machine_type) = get_basic_machine_info($conf, $forcemachine);
3389 $kvm //= 1 if is_native($arch);
4317f69f 3390
d731ecbe
WB
3391 if ($kvm) {
3392 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n"
3393 if !defined kvm_version();
3394 }
bfcd9b7e 3395
a3c52213
DM
3396 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
3397 $vernum = $1*1000000+$2*1000;
3398 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
3399 $vernum = $1*1000000+$2*1000+$3;
3400 }
3401
a3c52213 3402 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
3403
3404 my $have_ovz = -f '/proc/vz/vestat';
3405
db656e5f 3406 my $q35 = machine_type_is_q35($conf);
4d3f29ed 3407 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
249c4a6c
AD
3408 my $use_old_bios_files = undef;
3409 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
db656e5f 3410
f08e17c7
AD
3411 my $cpuunits = defined($conf->{cpuunits}) ?
3412 $conf->{cpuunits} : $defaults->{cpuunits};
3413
6908fd9b 3414 push @$cmd, get_command_for_arch($arch);
1e3baf05
DM
3415
3416 push @$cmd, '-id', $vmid;
3417
e4d4cda1
HR
3418 my $vmname = $conf->{name} || "vm$vmid";
3419
3420 push @$cmd, '-name', $vmname;
3421
1e3baf05
DM
3422 my $use_virtio = 0;
3423
c971c4f2
AD
3424 my $qmpsocket = qmp_socket($vmid);
3425 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
3426 push @$cmd, '-mon', "chardev=qmp,mode=control";
3427
71bd73b5 3428 if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 12)) {
b4496b9e 3429 push @$cmd, '-chardev', "socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5";
71bd73b5
DC
3430 push @$cmd, '-mon', "chardev=qmp-event,mode=control";
3431 }
1e3baf05 3432
6b64503e 3433 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 3434
1e3baf05
DM
3435 push @$cmd, '-daemonize';
3436
2796e7d5
DM
3437 if ($conf->{smbios1}) {
3438 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
3439 }
3440
6ee499ff
DC
3441 if ($conf->{vmgenid}) {
3442 push @$devices, '-device', 'vmgenid,guid='.$conf->{vmgenid};
3443 }
3444
96ed3574 3445 my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch);
3edb45e7 3446 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
96ed3574 3447 die "uefi base image not found\n" if ! -f $ovmf_code;
2ddc0a5c 3448
4dcce9ee 3449 my $path;
13bca7b4 3450 my $format;
4dcce9ee
TL
3451 if (my $efidisk = $conf->{efidisk0}) {
3452 my $d = PVE::JSONSchema::parse_property_string($efidisk_fmt, $efidisk);
2ddc0a5c 3453 my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
13bca7b4 3454 $format = $d->{format};
2ddc0a5c
DC
3455 if ($storeid) {
3456 $path = PVE::Storage::path($storecfg, $d->{file});
13bca7b4
WB
3457 if (!defined($format)) {
3458 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
3459 $format = qemu_img_format($scfg, $volname);
3460 }
2ddc0a5c
DC
3461 } else {
3462 $path = $d->{file};
13bca7b4
WB
3463 die "efidisk format must be specified\n"
3464 if !defined($format);
2ddc0a5c 3465 }
2ddc0a5c 3466 } else {
4dcce9ee
TL
3467 warn "no efidisk configured! Using temporary efivars disk.\n";
3468 $path = "/tmp/$vmid-ovmf.fd";
96ed3574 3469 PVE::Tools::file_copy($ovmf_vars, $path, -s $ovmf_vars);
13bca7b4 3470 $format = 'raw';
2ddc0a5c 3471 }
4dcce9ee 3472
96ed3574 3473 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmf_code";
2bfbee03 3474 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
a783c78e
AD
3475 }
3476
da8b4189 3477
d40e5e18 3478 # add usb controllers
d559309f 3479 my @usbcontrollers = PVE::QemuServer::USB::get_usb_controllers($conf, $bridges, $arch, $machine_type, $usbdesc->{format}, $MAX_USB_DEVICES);
d40e5e18 3480 push @$devices, @usbcontrollers if @usbcontrollers;
55655ebc 3481 my $vga = parse_vga($conf->{vga});
2fa3151e 3482
55655ebc
DC
3483 my $qxlnum = vga_conf_has_spice($conf->{vga});
3484 $vga->{type} = 'qxl' if $qxlnum;
2fa3151e 3485
55655ebc 3486 if (!$vga->{type}) {
869ad4a7
WB
3487 if ($arch eq 'aarch64') {
3488 $vga->{type} = 'virtio';
3489 } elsif (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
55655ebc 3490 $vga->{type} = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
a2a5cd64 3491 } else {
55655ebc 3492 $vga->{type} = ($winversion >= 6) ? 'std' : 'cirrus';
a2a5cd64 3493 }
5acbfe9e
DM
3494 }
3495
1e3baf05 3496 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
3497 my $tablet;
3498 if (defined($conf->{tablet})) {
3499 $tablet = $conf->{tablet};
3500 } else {
3501 $tablet = $defaults->{tablet};
590e698c 3502 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
55655ebc 3503 $tablet = 0 if $vga->{type} =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
5acbfe9e
DM
3504 }
3505
d559309f
WB
3506 if ($tablet) {
3507 push @$devices, '-device', print_tabletdevice_full($conf, $arch) if $tablet;
3508 my $kbd = print_keyboarddevice_full($conf, $arch);
3509 push @$devices, '-device', $kbd if defined($kbd);
3510 }
b467f79a 3511
16a91d65 3512 my $kvm_off = 0;
4317f69f
AD
3513 my $gpu_passthrough;
3514
1e3baf05 3515 # host pci devices
040b06b7 3516 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2e3b7e2a
AD
3517 my $d = parse_hostpci($conf->{"hostpci$i"});
3518 next if !$d;
3519
3520 my $pcie = $d->{pcie};
3521 if($pcie){
3522 die "q35 machine model is not enabled" if !$q35;
3523 $pciaddr = print_pcie_addr("hostpci$i");
3524 }else{
d559309f 3525 $pciaddr = print_pci_addr("hostpci$i", $bridges, $arch, $machine_type);
2e3b7e2a
AD
3526 }
3527
1f4f447b 3528 my $rombar = defined($d->{rombar}) && !$d->{rombar} ? ',rombar=0' : '';
9009150b 3529 my $romfile = $d->{romfile};
456a6fec 3530
1f4f447b
WB
3531 my $xvga = '';
3532 if ($d->{'x-vga'}) {
3533 $xvga = ',x-vga=on';
16a91d65 3534 $kvm_off = 1;
55655ebc 3535 $vga->{type} = 'none';
4317f69f
AD
3536 $gpu_passthrough = 1;
3537
230a4382
AD
3538 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
3539 $xvga = "";
3540 }
137483c0 3541 }
4543ecf0
AD
3542 my $pcidevices = $d->{pciid};
3543 my $multifunction = 1 if @$pcidevices > 1;
2e3b7e2a 3544
4543ecf0
AD
3545 my $j=0;
3546 foreach my $pcidevice (@$pcidevices) {
2e3b7e2a 3547
4543ecf0
AD
3548 my $id = "hostpci$i";
3549 $id .= ".$j" if $multifunction;
3550 my $addr = $pciaddr;
3551 $addr .= ".$j" if $multifunction;
6ea8cd3b 3552 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
4543ecf0
AD
3553
3554 if($j == 0){
3555 $devicestr .= "$rombar$xvga";
3556 $devicestr .= ",multifunction=on" if $multifunction;
456a6fec 3557 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
4543ecf0
AD
3558 }
3559
3560 push @$devices, '-device', $devicestr;
3561 $j++;
3562 }
1e3baf05
DM
3563 }
3564
3565 # usb devices
d40e5e18
DC
3566 my @usbdevices = PVE::QemuServer::USB::get_usb_devices($conf, $usbdesc->{format}, $MAX_USB_DEVICES);
3567 push @$devices, @usbdevices if @usbdevices;
1e3baf05 3568 # serial devices
bae179aa 3569 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 3570 if (my $path = $conf->{"serial$i"}) {
9f9d2fb2
DM
3571 if ($path eq 'socket') {
3572 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3573 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
91b01bbb
WB
3574 # On aarch64, serial0 is the UART device. Qemu only allows
3575 # connecting UART devices via the '-serial' command line, as
3576 # the device has a fixed slot on the hardware...
3577 if ($arch eq 'aarch64' && $i == 0) {
3578 push @$devices, '-serial', "chardev:serial$i";
3579 } else {
3580 push @$devices, '-device', "isa-serial,chardev=serial$i";
3581 }
9f9d2fb2
DM
3582 } else {
3583 die "no such serial device\n" if ! -c $path;
3584 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3585 push @$devices, '-device', "isa-serial,chardev=serial$i";
3586 }
34978be3 3587 }
1e3baf05
DM
3588 }
3589
3590 # parallel devices
1989a89c 3591 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 3592 if (my $path = $conf->{"parallel$i"}) {
19672434 3593 die "no such parallel device\n" if ! -c $path;
32e69805 3594 my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
4c5dbaf6 3595 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
5bdcf937 3596 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 3597 }
1e3baf05
DM
3598 }
3599
19672434 3600
1e3baf05
DM
3601 my $sockets = 1;
3602 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3603 $sockets = $conf->{sockets} if $conf->{sockets};
3604
3605 my $cores = $conf->{cores} || 1;
3bd18e48 3606
de9d1e55 3607 my $maxcpus = $sockets * $cores;
76267728 3608
de9d1e55 3609 my $vcpus = $conf->{vcpus} ? $conf->{vcpus} : $maxcpus;
76267728 3610
de9d1e55
AD
3611 my $allowed_vcpus = $cpuinfo->{cpus};
3612
6965d5d1 3613 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
de9d1e55
AD
3614 if ($allowed_vcpus < $maxcpus);
3615
69c81430 3616 if($hotplug_features->{cpu} && qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 7)) {
1e3baf05 3617
69c81430
AD
3618 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3619 for (my $i = 2; $i <= $vcpus; $i++) {
3620 my $cpustr = print_cpu_device($conf,$i);
3621 push @$cmd, '-device', $cpustr;
3622 }
3623
3624 } else {
3625
3626 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3627 }
1e3baf05
DM
3628 push @$cmd, '-nodefaults';
3629
32baffb4 3630 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 3631
0888fdce
DM
3632 my $bootindex_hash = {};
3633 my $i = 1;
3634 foreach my $o (split(//, $bootorder)) {
3635 $bootindex_hash->{$o} = $i*100;
3636 $i++;
afdb31d5 3637 }
3b408e82 3638
dbea4415 3639 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
1e3baf05 3640
6b64503e 3641 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 3642
6b64503e 3643 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 3644
84902837 3645 if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none'){
d559309f 3646 push @$devices, '-device', print_vga_device($conf, $vga, $arch, $machine_type, undef, $qxlnum, $bridges);
b7be4ba9
AD
3647 my $socket = vnc_socket($vmid);
3648 push @$cmd, '-vnc', "unix:$socket,x509,password";
3649 } else {
55655ebc 3650 push @$cmd, '-vga', 'none' if $vga->{type} eq 'none';
b7be4ba9
AD
3651 push @$cmd, '-nographic';
3652 }
3653
1e3baf05 3654 # time drift fix
6b64503e 3655 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 3656
8c559505 3657 my $useLocaltime = $conf->{localtime};
1e3baf05 3658
4317f69f
AD
3659 if ($winversion >= 5) { # windows
3660 $useLocaltime = 1 if !defined($conf->{localtime});
7a131888 3661
4317f69f
AD
3662 # use time drift fix when acpi is enabled
3663 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
3664 $tdf = 1 if !defined($conf->{tdf});
462e8d19 3665 }
4317f69f 3666 }
462e8d19 3667
4317f69f
AD
3668 if ($winversion >= 6) {
3669 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3670 push @$cmd, '-no-hpet';
1e3baf05
DM
3671 }
3672
8c559505
DM
3673 push @$rtcFlags, 'driftfix=slew' if $tdf;
3674
74c02ef7 3675 if (!$kvm) {
8c559505 3676 push @$machineFlags, 'accel=tcg';
7f0b5beb 3677 }
1e3baf05 3678
952958bc
DM
3679 if ($machine_type) {
3680 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
3681 }
3682
8c559505
DM
3683 if ($conf->{startdate}) {
3684 push @$rtcFlags, "base=$conf->{startdate}";
3685 } elsif ($useLocaltime) {
3686 push @$rtcFlags, 'base=localtime';
3687 }
1e3baf05 3688
4fc262bd 3689 push @$cmd, get_cpu_options($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, $gpu_passthrough);
519ed28c 3690
0567a4d5
AD
3691 PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3692
1e3baf05
DM
3693 push @$cmd, '-S' if $conf->{freeze};
3694
b20df606 3695 push @$cmd, '-k', $conf->{keyboard} if defined($conf->{keyboard});
1e3baf05
DM
3696
3697 # enable sound
3698 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3699 #push @$cmd, '-soundhw', 'es1370';
3700 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 3701
9d66b397 3702 if (parse_guest_agent($conf)->{enabled}) {
7a6c2150 3703 my $qgasocket = qmp_socket($vmid, 1);
d559309f 3704 my $pciaddr = print_pci_addr("qga0", $bridges, $arch, $machine_type);
ab6a046f
AD
3705 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3706 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3707 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3708 }
3709
1d794448 3710 my $spice_port;
2fa3151e 3711
590e698c
DM
3712 if ($qxlnum) {
3713 if ($qxlnum > 1) {
ac087616 3714 if ($winversion){
590e698c 3715 for(my $i = 1; $i < $qxlnum; $i++){
d559309f 3716 push @$devices, '-device', print_vga_device($conf, $vga, $arch, $machine_type, $i, $qxlnum, $bridges);
590e698c
DM
3717 }
3718 } else {
3719 # assume other OS works like Linux
55655ebc
DC
3720 my ($ram, $vram) = ("134217728", "67108864");
3721 if ($vga->{memory}) {
3722 $ram = PVE::Tools::convert_size($qxlnum*4*$vga->{memory}, 'mb' => 'b');
3723 $vram = PVE::Tools::convert_size($qxlnum*2*$vga->{memory}, 'mb' => 'b');
3724 }
3725 push @$cmd, '-global', "qxl-vga.ram_size=$ram";
3726 push @$cmd, '-global', "qxl-vga.vram_size=$vram";
2fa3151e
AD
3727 }
3728 }
3729
d559309f 3730 my $pciaddr = print_pci_addr("spice", $bridges, $arch, $machine_type);
95a4b4a9 3731
af0eba7e
WB
3732 my $nodename = PVE::INotify::nodename();
3733 my $pfamily = PVE::Tools::get_host_address_family($nodename);
91152441
WB
3734 my @nodeaddrs = PVE::Tools::getaddrinfo_all('localhost', family => $pfamily);
3735 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3736 my $localhost = PVE::Network::addr_to_ip($nodeaddrs[0]->{addr});
3737 $spice_port = PVE::Tools::next_spice_port($pfamily, $localhost);
943340a6 3738
91152441 3739 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
1011b570 3740
d2da6d9b
AD
3741 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3742 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3743 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
1011b570
DM
3744 }
3745
8d9ae0d2
DM
3746 # enable balloon by default, unless explicitly disabled
3747 if (!defined($conf->{balloon}) || $conf->{balloon}) {
d559309f 3748 $pciaddr = print_pci_addr("balloon0", $bridges, $arch, $machine_type);
8d9ae0d2
DM
3749 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3750 }
1e3baf05 3751
0ea9541d
DM
3752 if ($conf->{watchdog}) {
3753 my $wdopts = parse_watchdog($conf->{watchdog});
d559309f 3754 $pciaddr = print_pci_addr("watchdog", $bridges, $arch, $machine_type);
0a40e8ea 3755 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
3756 push @$devices, '-device', "$watchdog$pciaddr";
3757 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
3758 }
3759
1e3baf05 3760 my $vollist = [];
941e0c42 3761 my $scsicontroller = {};
26ee04b6 3762 my $ahcicontroller = {};
cdd20088 3763 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05 3764
5881b913
DM
3765 # Add iscsi initiator name if available
3766 if (my $initiator = get_initiator_name()) {
3767 push @$devices, '-iscsi', "initiator-name=$initiator";
3768 }
3769
1e3baf05
DM
3770 foreach_drive($conf, sub {
3771 my ($ds, $drive) = @_;
3772
ff1a2432 3773 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 3774 push @$vollist, $drive->{file};
ff1a2432 3775 }
afdb31d5 3776
4dcce9ee
TL
3777 # ignore efidisk here, already added in bios/fw handling code above
3778 return if $drive->{interface} eq 'efidisk';
3779
1e3baf05 3780 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
3781
3782 if (drive_is_cdrom ($drive)) {
3783 if ($bootindex_hash->{d}) {
3784 $drive->{bootindex} = $bootindex_hash->{d};
3785 $bootindex_hash->{d} += 1;
3786 }
3787 } else {
3788 if ($bootindex_hash->{c}) {
3789 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
3790 $bootindex_hash->{c} += 1;
3791 }
3792 }
3793
51f492cd
AD
3794 if($drive->{interface} eq 'virtio'){
3795 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread};
3796 }
3797
941e0c42 3798 if ($drive->{interface} eq 'scsi') {
cdd20088 3799
ee034f5c 3800 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
6731a4cf 3801
d559309f 3802 $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch, $machine_type);
a1b7d579 3803 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
fc8b40fd
AD
3804
3805 my $iothread = '';
3806 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{iothread}){
3807 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3808 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
e7a5104d
DC
3809 } elsif ($drive->{iothread}) {
3810 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
fc8b40fd
AD
3811 }
3812
6e11f143
AD
3813 my $queues = '';
3814 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{queues}){
3815 $queues = ",num_queues=$drive->{queues}";
3816 }
3817
3818 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
cdd20088 3819 $scsicontroller->{$controller}=1;
941e0c42 3820 }
3b408e82 3821
26ee04b6
DA
3822 if ($drive->{interface} eq 'sata') {
3823 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
d559309f 3824 $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch, $machine_type);
5bdcf937 3825 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
3826 $ahcicontroller->{$controller}=1;
3827 }
46f58b5f 3828
15b21acc
MR
3829 my $drive_cmd = print_drive_full($storecfg, $vmid, $drive);
3830 push @$devices, '-drive',$drive_cmd;
d559309f 3831 push @$devices, '-device', print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type);
1e3baf05
DM
3832 });
3833
cc4d6182 3834 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 3835 next if !$conf->{"net$i"};
cc4d6182
DA
3836 my $d = parse_net($conf->{"net$i"});
3837 next if !$d;
1e3baf05 3838
cc4d6182 3839 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 3840
cc4d6182
DA
3841 if ($bootindex_hash->{n}) {
3842 $d->{bootindex} = $bootindex_hash->{n};
3843 $bootindex_hash->{n} += 1;
3844 }
1e3baf05 3845
d559309f 3846 my $netdevfull = print_netdev_full($vmid, $conf, $arch, $d, "net$i");
5bdcf937
AD
3847 push @$devices, '-netdev', $netdevfull;
3848
d559309f 3849 my $netdevicefull = print_netdevice_full($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files, $arch, $machine_type);
5bdcf937
AD
3850 push @$devices, '-device', $netdevicefull;
3851 }
1e3baf05 3852
db656e5f
DM
3853 if (!$q35) {
3854 # add pci bridges
fc79e813
AD
3855 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3856 $bridges->{1} = 1;
3857 $bridges->{2} = 1;
3858 }
3859
6731a4cf
AD
3860 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3861
f8e83f05 3862 while (my ($k, $v) = each %$bridges) {
d559309f 3863 $pciaddr = print_pci_addr("pci.$k", undef, $arch, $machine_type);
f8e83f05
AD
3864 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3865 }
19672434
DM
3866 }
3867
1e3baf05
DM
3868 # add custom args
3869 if ($conf->{args}) {
3ada46c9 3870 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
3871 push @$cmd, @$aa;
3872 }
3873
5bdcf937 3874 push @$cmd, @$devices;
be190583 3875 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 3876 if scalar(@$rtcFlags);
be190583 3877 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
3878 if scalar(@$machineFlags);
3879 push @$cmd, '-global', join(',', @$globalFlags)
3880 if scalar(@$globalFlags);
3881
1d794448 3882 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
1e3baf05 3883}
19672434 3884
1e3baf05
DM
3885sub vnc_socket {
3886 my ($vmid) = @_;
3887 return "${var_run_tmpdir}/$vmid.vnc";
3888}
3889
943340a6 3890sub spice_port {
1011b570 3891 my ($vmid) = @_;
943340a6 3892
1d794448 3893 my $res = vm_mon_cmd($vmid, 'query-spice');
943340a6
DM
3894
3895 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
3896}
3897
c971c4f2 3898sub qmp_socket {
71bd73b5 3899 my ($vmid, $qga, $name) = @_;
693d12a2 3900 my $sockettype = $qga ? 'qga' : 'qmp';
71bd73b5
DC
3901 my $ext = $name ? '-'.$name : '';
3902 return "${var_run_tmpdir}/$vmid$ext.$sockettype";
c971c4f2
AD
3903}
3904
1e3baf05
DM
3905sub pidfile_name {
3906 my ($vmid) = @_;
3907 return "${var_run_tmpdir}/$vmid.pid";
3908}
3909
86fdcfb2
DA
3910sub vm_devices_list {
3911 my ($vmid) = @_;
3912
ceea9078 3913 my $res = vm_mon_cmd($vmid, 'query-pci');
f721624b 3914 my $devices_to_check = [];
ceea9078
DM
3915 my $devices = {};
3916 foreach my $pcibus (@$res) {
f721624b
DC
3917 push @$devices_to_check, @{$pcibus->{devices}},
3918 }
3919
3920 while (@$devices_to_check) {
3921 my $to_check = [];
3922 for my $d (@$devices_to_check) {
3923 $devices->{$d->{'qdev_id'}} = 1 if $d->{'qdev_id'};
3924 next if !$d->{'pci_bridge'};
3925
3926 $devices->{$d->{'qdev_id'}} += scalar(@{$d->{'pci_bridge'}->{devices}});
3927 push @$to_check, @{$d->{'pci_bridge'}->{devices}};
f78cc802 3928 }
f721624b 3929 $devices_to_check = $to_check;
f78cc802
AD
3930 }
3931
3932 my $resblock = vm_mon_cmd($vmid, 'query-block');
3933 foreach my $block (@$resblock) {
3934 if($block->{device} =~ m/^drive-(\S+)/){
3935 $devices->{$1} = 1;
1dc4f496
DM
3936 }
3937 }
86fdcfb2 3938
3d7389fe
DM
3939 my $resmice = vm_mon_cmd($vmid, 'query-mice');
3940 foreach my $mice (@$resmice) {
3941 if ($mice->{name} eq 'QEMU HID Tablet') {
3942 $devices->{tablet} = 1;
3943 last;
3944 }
3945 }
3946
deb091c5
DC
3947 # for usb devices there is no query-usb
3948 # but we can iterate over the entries in
3949 # qom-list path=/machine/peripheral
3950 my $resperipheral = vm_mon_cmd($vmid, 'qom-list', path => '/machine/peripheral');
3951 foreach my $per (@$resperipheral) {
3952 if ($per->{name} =~ m/^usb\d+$/) {
3953 $devices->{$per->{name}} = 1;
3954 }
3955 }
3956
1dc4f496 3957 return $devices;
86fdcfb2
DA
3958}
3959
ec21aa11 3960sub vm_deviceplug {
d559309f 3961 my ($storecfg, $conf, $vmid, $deviceid, $device, $arch, $machine_type) = @_;
ae57f6b3 3962
db656e5f
DM
3963 my $q35 = machine_type_is_q35($conf);
3964
95d6343b
DA
3965 my $devices_list = vm_devices_list($vmid);
3966 return 1 if defined($devices_list->{$deviceid});
3967
d559309f 3968 qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid, $arch, $machine_type); # add PCI bridge if we need it for the device
fee46675 3969
3d7389fe 3970 if ($deviceid eq 'tablet') {
fee46675 3971
d559309f
WB
3972 qemu_deviceadd($vmid, print_tabletdevice_full($conf, $arch));
3973
3974 } elsif ($deviceid eq 'keyboard') {
3975
3976 qemu_deviceadd($vmid, print_keyboarddevice_full($conf, $arch));
3d7389fe 3977
4eb68604
DC
3978 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3979
f745762b
DC
3980 die "usb hotplug currently not reliable\n";
3981 # since we can't reliably hot unplug all added usb devices
3982 # and usb passthrough disables live migration
3983 # we disable usb hotplugging for now
4eb68604
DC
3984 qemu_deviceadd($vmid, PVE::QemuServer::USB::print_usbdevice_full($conf, $deviceid, $device));
3985
fee46675 3986 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
40f28a9f 3987
22de899a
AD
3988 qemu_iothread_add($vmid, $deviceid, $device);
3989
fee46675 3990 qemu_driveadd($storecfg, $vmid, $device);
d559309f 3991 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, $arch, $machine_type);
fee46675 3992
5e5dcb73 3993 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3994 eval { qemu_deviceaddverify($vmid, $deviceid); };
3995 if (my $err = $@) {
63c2da2f
DM
3996 eval { qemu_drivedel($vmid, $deviceid); };
3997 warn $@ if $@;
fee46675 3998 die $err;
5e5dcb73 3999 }
cfc817c7 4000
2733141c 4001 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
fee46675 4002
fc8b40fd 4003
cdd20088 4004 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
d559309f 4005 my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type);
a1b7d579 4006 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
2733141c
AD
4007
4008 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
fee46675 4009
fc8b40fd
AD
4010 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
4011 qemu_iothread_add($vmid, $deviceid, $device);
4012 $devicefull .= ",iothread=iothread-$deviceid";
4013 }
4014
6e11f143
AD
4015 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues}) {
4016 $devicefull .= ",num_queues=$device->{queues}";
4017 }
4018
cfc817c7 4019 qemu_deviceadd($vmid, $devicefull);
fee46675 4020 qemu_deviceaddverify($vmid, $deviceid);
cfc817c7 4021
fee46675
DM
4022 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
4023
d559309f 4024 qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device, $arch, $machine_type);
fee46675 4025 qemu_driveadd($storecfg, $vmid, $device);
a1b7d579 4026
d559309f 4027 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, $arch, $machine_type);
fee46675
DM
4028 eval { qemu_deviceadd($vmid, $devicefull); };
4029 if (my $err = $@) {
63c2da2f
DM
4030 eval { qemu_drivedel($vmid, $deviceid); };
4031 warn $@ if $@;
fee46675 4032 die $err;
a4f091a0 4033 }
a4f091a0 4034
fee46675
DM
4035 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
4036
d559309f 4037 return undef if !qemu_netdevadd($vmid, $conf, $arch, $device, $deviceid);
8718099c
AD
4038
4039 my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
4040 my $use_old_bios_files = undef;
4041 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
4042
d559309f 4043 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files, $arch, $machine_type);
2630d2a9 4044 qemu_deviceadd($vmid, $netdevicefull);
fee46675
DM
4045 eval { qemu_deviceaddverify($vmid, $deviceid); };
4046 if (my $err = $@) {
4047 eval { qemu_netdevdel($vmid, $deviceid); };
4048 warn $@ if $@;
4049 die $err;
2630d2a9 4050 }
2630d2a9 4051
fee46675 4052 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
b467f79a 4053
40f28a9f 4054 my $bridgeid = $2;
d559309f 4055 my $pciaddr = print_pci_addr($deviceid, undef, $arch, $machine_type);
40f28a9f 4056 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
a1b7d579 4057
40f28a9f 4058 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
4059 qemu_deviceaddverify($vmid, $deviceid);
4060
4061 } else {
a1b7d579 4062 die "can't hotplug device '$deviceid'\n";
40f28a9f
AD
4063 }
4064
5e5dcb73 4065 return 1;
a4dea331
DA
4066}
4067
3eec5767 4068# fixme: this should raise exceptions on error!
ec21aa11 4069sub vm_deviceunplug {
f19d1c47 4070 my ($vmid, $conf, $deviceid) = @_;
873c2d69 4071
95d6343b
DA
4072 my $devices_list = vm_devices_list($vmid);
4073 return 1 if !defined($devices_list->{$deviceid});
4074
63c2da2f
DM
4075 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
4076
d559309f 4077 if ($deviceid eq 'tablet' || $deviceid eq 'keyboard') {
63c2da2f 4078
3d7389fe 4079 qemu_devicedel($vmid, $deviceid);
3d7389fe 4080
4eb68604
DC
4081 } elsif ($deviceid =~ m/^usb\d+$/) {
4082
f745762b
DC
4083 die "usb hotplug currently not reliable\n";
4084 # when unplugging usb devices this way,
4085 # there may be remaining usb controllers/hubs
4086 # so we disable it for now
4eb68604
DC
4087 qemu_devicedel($vmid, $deviceid);
4088 qemu_devicedelverify($vmid, $deviceid);
4089
63c2da2f 4090 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
f19d1c47 4091
5e5dcb73 4092 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
4093 qemu_devicedelverify($vmid, $deviceid);
4094 qemu_drivedel($vmid, $deviceid);
22de899a
AD
4095 qemu_iothread_del($conf, $vmid, $deviceid);
4096
2733141c 4097 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
a1b7d579 4098
63c2da2f 4099 qemu_devicedel($vmid, $deviceid);
8ce30dde 4100 qemu_devicedelverify($vmid, $deviceid);
fc8b40fd 4101 qemu_iothread_del($conf, $vmid, $deviceid);
a1b7d579 4102
63c2da2f 4103 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
cfc817c7 4104
63c2da2f
DM
4105 qemu_devicedel($vmid, $deviceid);
4106 qemu_drivedel($vmid, $deviceid);
a1b7d579 4107 qemu_deletescsihw($conf, $vmid, $deviceid);
8ce30dde 4108
63c2da2f 4109 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
a4f091a0 4110
2630d2a9 4111 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
4112 qemu_devicedelverify($vmid, $deviceid);
4113 qemu_netdevdel($vmid, $deviceid);
4114
4115 } else {
4116 die "can't unplug device '$deviceid'\n";
2630d2a9
DA
4117 }
4118
5e5dcb73
DA
4119 return 1;
4120}
4121
4122sub qemu_deviceadd {
4123 my ($vmid, $devicefull) = @_;
873c2d69 4124
d695b5b7
AD
4125 $devicefull = "driver=".$devicefull;
4126 my %options = split(/[=,]/, $devicefull);
f19d1c47 4127
d695b5b7 4128 vm_mon_cmd($vmid, "device_add" , %options);
5e5dcb73 4129}
afdb31d5 4130
5e5dcb73 4131sub qemu_devicedel {
fee46675 4132 my ($vmid, $deviceid) = @_;
63c2da2f 4133
5a77d8c1 4134 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
5e5dcb73
DA
4135}
4136
22de899a
AD
4137sub qemu_iothread_add {
4138 my($vmid, $deviceid, $device) = @_;
4139
4140 if ($device->{iothread}) {
4141 my $iothreads = vm_iothreads_list($vmid);
4142 qemu_objectadd($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
4143 }
4144}
4145
4146sub qemu_iothread_del {
4147 my($conf, $vmid, $deviceid) = @_;
4148
4149 my $device = parse_drive($deviceid, $conf->{$deviceid});
4150 if ($device->{iothread}) {
4151 my $iothreads = vm_iothreads_list($vmid);
4152 qemu_objectdel($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
4153 }
4154}
4155
4d3f29ed
AD
4156sub qemu_objectadd {
4157 my($vmid, $objectid, $qomtype) = @_;
4158
4159 vm_mon_cmd($vmid, "object-add", id => $objectid, "qom-type" => $qomtype);
4160
4161 return 1;
4162}
4163
4164sub qemu_objectdel {
4165 my($vmid, $objectid) = @_;
4166
4167 vm_mon_cmd($vmid, "object-del", id => $objectid);
4168
4169 return 1;
4170}
4171
5e5dcb73 4172sub qemu_driveadd {
fee46675 4173 my ($storecfg, $vmid, $device) = @_;
5e5dcb73
DA
4174
4175 my $drive = print_drive_full($storecfg, $vmid, $device);
7a69fc3c 4176 $drive =~ s/\\/\\\\/g;
8ead5ec7 4177 my $ret = vm_human_monitor_command($vmid, "drive_add auto \"$drive\"");
fee46675 4178
5e5dcb73 4179 # If the command succeeds qemu prints: "OK"
fee46675
DM
4180 return 1 if $ret =~ m/OK/s;
4181
4182 die "adding drive failed: $ret\n";
5e5dcb73 4183}
afdb31d5 4184
5e5dcb73
DA
4185sub qemu_drivedel {
4186 my($vmid, $deviceid) = @_;
873c2d69 4187
7b7c6d1b 4188 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73 4189 $ret =~ s/^\s+//;
a1b7d579 4190
63c2da2f 4191 return 1 if $ret eq "";
a1b7d579 4192
63c2da2f 4193 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
a1b7d579
DM
4194 return 1 if $ret =~ m/Device \'.*?\' not found/s;
4195
63c2da2f 4196 die "deleting drive $deviceid failed : $ret\n";
5e5dcb73 4197}
f19d1c47 4198
5e5dcb73 4199sub qemu_deviceaddverify {
fee46675 4200 my ($vmid, $deviceid) = @_;
873c2d69 4201
5e5dcb73
DA
4202 for (my $i = 0; $i <= 5; $i++) {
4203 my $devices_list = vm_devices_list($vmid);
4204 return 1 if defined($devices_list->{$deviceid});
4205 sleep 1;
afdb31d5 4206 }
fee46675
DM
4207
4208 die "error on hotplug device '$deviceid'\n";
5e5dcb73 4209}
afdb31d5 4210
5e5dcb73
DA
4211
4212sub qemu_devicedelverify {
63c2da2f
DM
4213 my ($vmid, $deviceid) = @_;
4214
a1b7d579 4215 # need to verify that the device is correctly removed as device_del
63c2da2f 4216 # is async and empty return is not reliable
5e5dcb73 4217
5e5dcb73
DA
4218 for (my $i = 0; $i <= 5; $i++) {
4219 my $devices_list = vm_devices_list($vmid);
4220 return 1 if !defined($devices_list->{$deviceid});
4221 sleep 1;
afdb31d5 4222 }
63c2da2f
DM
4223
4224 die "error on hot-unplugging device '$deviceid'\n";
873c2d69
DA
4225}
4226
cdd20088 4227sub qemu_findorcreatescsihw {
d559309f 4228 my ($storecfg, $conf, $vmid, $device, $arch, $machine_type) = @_;
cfc817c7 4229
ee034f5c 4230 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
2733141c
AD
4231
4232 my $scsihwid="$controller_prefix$controller";
cfc817c7
DA
4233 my $devices_list = vm_devices_list($vmid);
4234
cdd20088 4235 if(!defined($devices_list->{$scsihwid})) {
d559309f 4236 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device, $arch, $machine_type);
cfc817c7 4237 }
fee46675 4238
cfc817c7
DA
4239 return 1;
4240}
4241
8ce30dde
AD
4242sub qemu_deletescsihw {
4243 my ($conf, $vmid, $opt) = @_;
4244
4245 my $device = parse_drive($opt, $conf->{$opt});
4246
a1511b3c 4247 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
2733141c
AD
4248 vm_deviceunplug($vmid, $conf, "virtioscsi$device->{index}");
4249 return 1;
4250 }
4251
ee034f5c 4252 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
8ce30dde
AD
4253
4254 my $devices_list = vm_devices_list($vmid);
4255 foreach my $opt (keys %{$devices_list}) {
74479ee9 4256 if (PVE::QemuServer::is_valid_drivename($opt)) {
8ce30dde
AD
4257 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
4258 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
4259 return 1;
4260 }
4261 }
4262 }
4263
4264 my $scsihwid="scsihw$controller";
4265
4266 vm_deviceunplug($vmid, $conf, $scsihwid);
4267
4268 return 1;
4269}
4270
281fedb3 4271sub qemu_add_pci_bridge {
d559309f 4272 my ($storecfg, $conf, $vmid, $device, $arch, $machine_type) = @_;
40f28a9f
AD
4273
4274 my $bridges = {};
281fedb3
DM
4275
4276 my $bridgeid;
4277
d559309f 4278 print_pci_addr($device, $bridges, $arch, $machine_type);
40f28a9f
AD
4279
4280 while (my ($k, $v) = each %$bridges) {
4281 $bridgeid = $k;
4282 }
fee46675 4283 return 1 if !defined($bridgeid) || $bridgeid < 1;
281fedb3 4284
40f28a9f
AD
4285 my $bridge = "pci.$bridgeid";
4286 my $devices_list = vm_devices_list($vmid);
4287
281fedb3 4288 if (!defined($devices_list->{$bridge})) {
d559309f 4289 vm_deviceplug($storecfg, $conf, $vmid, $bridge, $arch, $machine_type);
40f28a9f 4290 }
281fedb3 4291
40f28a9f
AD
4292 return 1;
4293}
4294
25088687
DM
4295sub qemu_set_link_status {
4296 my ($vmid, $device, $up) = @_;
4297
a1b7d579 4298 vm_mon_cmd($vmid, "set_link", name => $device,
25088687
DM
4299 up => $up ? JSON::true : JSON::false);
4300}
4301
2630d2a9 4302sub qemu_netdevadd {
d559309f 4303 my ($vmid, $conf, $arch, $device, $deviceid) = @_;
2630d2a9 4304
d559309f 4305 my $netdev = print_netdev_full($vmid, $conf, $arch, $device, $deviceid, 1);
73aa03b8 4306 my %options = split(/[=,]/, $netdev);
2630d2a9 4307
73aa03b8
AD
4308 vm_mon_cmd($vmid, "netdev_add", %options);
4309 return 1;
2630d2a9
DA
4310}
4311
4312sub qemu_netdevdel {
4313 my ($vmid, $deviceid) = @_;
4314
89c1e0f4 4315 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2630d2a9
DA
4316}
4317
16521d63 4318sub qemu_usb_hotplug {
d559309f 4319 my ($storecfg, $conf, $vmid, $deviceid, $device, $arch, $machine_type) = @_;
16521d63
DC
4320
4321 return if !$device;
4322
4323 # remove the old one first
4324 vm_deviceunplug($vmid, $conf, $deviceid);
4325
4326 # check if xhci controller is necessary and available
4327 if ($device->{usb3}) {
4328
4329 my $devicelist = vm_devices_list($vmid);
4330
4331 if (!$devicelist->{xhci}) {
d559309f 4332 my $pciaddr = print_pci_addr("xhci", undef, $arch, $machine_type);
16521d63
DC
4333 qemu_deviceadd($vmid, "nec-usb-xhci,id=xhci$pciaddr");
4334 }
4335 }
4336 my $d = parse_usb_device($device->{host});
4337 $d->{usb3} = $device->{usb3};
4338
4339 # add the new one
d559309f 4340 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d, $arch, $machine_type);
16521d63
DC
4341}
4342
838776ab 4343sub qemu_cpu_hotplug {
8edc9c08 4344 my ($vmid, $conf, $vcpus) = @_;
838776ab 4345
1e881b75
AD
4346 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
4347
8edc9c08
AD
4348 my $sockets = 1;
4349 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
4350 $sockets = $conf->{sockets} if $conf->{sockets};
4351 my $cores = $conf->{cores} || 1;
4352 my $maxcpus = $sockets * $cores;
838776ab 4353
8edc9c08 4354 $vcpus = $maxcpus if !$vcpus;
3a11fadb 4355
8edc9c08
AD
4356 die "you can't add more vcpus than maxcpus\n"
4357 if $vcpus > $maxcpus;
3a11fadb 4358
8edc9c08 4359 my $currentvcpus = $conf->{vcpus} || $maxcpus;
1e881b75 4360
eba3e64d 4361 if ($vcpus < $currentvcpus) {
1e881b75
AD
4362
4363 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4364
4365 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
4366 qemu_devicedel($vmid, "cpu$i");
4367 my $retry = 0;
4368 my $currentrunningvcpus = undef;
4369 while (1) {
4370 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4371 last if scalar(@{$currentrunningvcpus}) == $i-1;
961af8a3 4372 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
1e881b75
AD
4373 $retry++;
4374 sleep 1;
4375 }
4376 #update conf after each succesfull cpu unplug
4377 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4378 PVE::QemuConfig->write_config($vmid, $conf);
4379 }
4380 } else {
961af8a3 4381 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
1e881b75
AD
4382 }
4383
4384 return;
4385 }
838776ab 4386
8edc9c08 4387 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
961af8a3 4388 die "vcpus in running vm does not match its configuration\n"
8edc9c08 4389 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
838776ab 4390
eba3e64d
AD
4391 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4392
4393 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
4394 my $cpustr = print_cpu_device($conf, $i);
4395 qemu_deviceadd($vmid, $cpustr);
4396
4397 my $retry = 0;
4398 my $currentrunningvcpus = undef;
4399 while (1) {
4400 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4401 last if scalar(@{$currentrunningvcpus}) == $i;
961af8a3 4402 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
eba3e64d
AD
4403 sleep 1;
4404 $retry++;
4405 }
4406 #update conf after each succesfull cpu hotplug
4407 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4408 PVE::QemuConfig->write_config($vmid, $conf);
4409 }
4410 } else {
4411
4412 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
4413 vm_mon_cmd($vmid, "cpu-add", id => int($i));
4414 }
838776ab
AD
4415 }
4416}
4417
affd2f88 4418sub qemu_block_set_io_throttle {
277ca170
WB
4419 my ($vmid, $deviceid,
4420 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
9196a8ec
WB
4421 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
4422 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
4423 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
affd2f88 4424
f3f323a3
AD
4425 return if !check_running($vmid) ;
4426
277ca170
WB
4427 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
4428 bps => int($bps),
4429 bps_rd => int($bps_rd),
4430 bps_wr => int($bps_wr),
4431 iops => int($iops),
4432 iops_rd => int($iops_rd),
4433 iops_wr => int($iops_wr),
4434 bps_max => int($bps_max),
4435 bps_rd_max => int($bps_rd_max),
4436 bps_wr_max => int($bps_wr_max),
4437 iops_max => int($iops_max),
4438 iops_rd_max => int($iops_rd_max),
9196a8ec
WB
4439 iops_wr_max => int($iops_wr_max),
4440 bps_max_length => int($bps_max_length),
4441 bps_rd_max_length => int($bps_rd_max_length),
4442 bps_wr_max_length => int($bps_wr_max_length),
4443 iops_max_length => int($iops_max_length),
4444 iops_rd_max_length => int($iops_rd_max_length),
4445 iops_wr_max_length => int($iops_wr_max_length),
277ca170 4446 );
f3f323a3 4447
affd2f88
AD
4448}
4449
f5eb281a 4450# old code, only used to shutdown old VM after update
dab36e1e
DM
4451sub __read_avail {
4452 my ($fh, $timeout) = @_;
4453
4454 my $sel = new IO::Select;
4455 $sel->add($fh);
4456
4457 my $res = '';
4458 my $buf;
4459
4460 my @ready;
4461 while (scalar (@ready = $sel->can_read($timeout))) {
4462 my $count;
4463 if ($count = $fh->sysread($buf, 8192)) {
4464 if ($buf =~ /^(.*)\(qemu\) $/s) {
4465 $res .= $1;
4466 last;
4467 } else {
4468 $res .= $buf;
4469 }
4470 } else {
4471 if (!defined($count)) {
4472 die "$!\n";
4473 }
4474 last;
4475 }
4476 }
4477
4478 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 4479
dab36e1e
DM
4480 return $res;
4481}
4482
c1175c92
AD
4483sub qemu_block_resize {
4484 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4485
ed221350 4486 my $running = check_running($vmid);
c1175c92 4487
7246e8f9 4488 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
c1175c92
AD
4489
4490 return if !$running;
4491
4492 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4493
4494}
4495
1ab0057c
AD
4496sub qemu_volume_snapshot {
4497 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4498
ed221350 4499 my $running = check_running($vmid);
1ab0057c 4500
e5eaa028 4501 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
eba2b721 4502 vm_mon_cmd($vmid, 'blockdev-snapshot-internal-sync', device => $deviceid, name => $snap);
e5eaa028
WL
4503 } else {
4504 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4505 }
1ab0057c
AD
4506}
4507
fc46aff9
AD
4508sub qemu_volume_snapshot_delete {
4509 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4510
ed221350 4511 my $running = check_running($vmid);
fc46aff9 4512
a2f1554b
AD
4513 if($running) {
4514
4515 $running = undef;
4516 my $conf = PVE::QemuConfig->load_config($vmid);
4517 foreach_drive($conf, sub {
4518 my ($ds, $drive) = @_;
4519 $running = 1 if $drive->{file} eq $volid;
4520 });
4521 }
4522
1ef7592f 4523 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
eba2b721 4524 vm_mon_cmd($vmid, 'blockdev-snapshot-delete-internal-sync', device => $deviceid, name => $snap);
1ef7592f
AD
4525 } else {
4526 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4527 }
fc46aff9
AD
4528}
4529
264e519f
DM
4530sub set_migration_caps {
4531 my ($vmid) = @_;
a89fded1 4532
8b8345f3 4533 my $cap_ref = [];
a89fded1
AD
4534
4535 my $enabled_cap = {
8b8345f3 4536 "auto-converge" => 1,
0b0a47e8 4537 "xbzrle" => 1,
8b8345f3
DM
4538 "x-rdma-pin-all" => 0,
4539 "zero-blocks" => 0,
b62532e4 4540 "compress" => 0
a89fded1
AD
4541 };
4542
8b8345f3 4543 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
a89fded1 4544
8b8345f3 4545 for my $supported_capability (@$supported_capabilities) {
b463a3ce
SP
4546 push @$cap_ref, {
4547 capability => $supported_capability->{capability},
22430fa2
DM
4548 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4549 };
a89fded1
AD
4550 }
4551
8b8345f3
DM
4552 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4553}
a89fded1 4554
81d95ae1 4555my $fast_plug_option = {
7498eb64 4556 'lock' => 1,
81d95ae1 4557 'name' => 1,
a1b7d579 4558 'onboot' => 1,
81d95ae1
DM
4559 'shares' => 1,
4560 'startup' => 1,
b0ec896e 4561 'description' => 1,
ec647db4 4562 'protection' => 1,
8cad5e9b 4563 'vmstatestorage' => 1,
81d95ae1
DM
4564};
4565
3a11fadb
DM
4566# hotplug changes in [PENDING]
4567# $selection hash can be used to only apply specified options, for
4568# example: { cores => 1 } (only apply changed 'cores')
4569# $errors ref is used to return error messages
c427973b 4570sub vmconfig_hotplug_pending {
3a11fadb 4571 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
c427973b 4572
8e90138a 4573 my $defaults = load_defaults();
d559309f 4574 my ($arch, $machine_type) = get_basic_machine_info($conf, undef);
c427973b
DM
4575
4576 # commit values which do not have any impact on running VM first
3a11fadb
DM
4577 # Note: those option cannot raise errors, we we do not care about
4578 # $selection and always apply them.
4579
4580 my $add_error = sub {
4581 my ($opt, $msg) = @_;
4582 $errors->{$opt} = "hotplug problem - $msg";
4583 };
c427973b
DM
4584
4585 my $changes = 0;
4586 foreach my $opt (keys %{$conf->{pending}}) { # add/change
81d95ae1 4587 if ($fast_plug_option->{$opt}) {
c427973b
DM
4588 $conf->{$opt} = $conf->{pending}->{$opt};
4589 delete $conf->{pending}->{$opt};
4590 $changes = 1;
4591 }
4592 }
4593
4594 if ($changes) {
ffda963f
FG
4595 PVE::QemuConfig->write_config($vmid, $conf);
4596 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
c427973b
DM
4597 }
4598
b3c2bdd1 4599 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
c427973b 4600
3dc38fbb
WB
4601 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4602 while (my ($opt, $force) = each %$pending_delete_hash) {
3a11fadb 4603 next if $selection && !$selection->{$opt};
3a11fadb 4604 eval {
51a6f637
AD
4605 if ($opt eq 'hotplug') {
4606 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4607 } elsif ($opt eq 'tablet') {
b3c2bdd1 4608 die "skip\n" if !$hotplug_features->{usb};
3a11fadb 4609 if ($defaults->{tablet}) {
d559309f
WB
4610 vm_deviceplug($storecfg, $conf, $vmid, 'tablet', $arch, $machine_type);
4611 vm_deviceplug($storecfg, $conf, $vmid, 'keyboard', $arch, $machine_type)
4612 if $arch eq 'aarch64';
3a11fadb 4613 } else {
d559309f
WB
4614 vm_deviceunplug($vmid, $conf, 'tablet');
4615 vm_deviceunplug($vmid, $conf, 'keyboard') if $arch eq 'aarch64';
3a11fadb 4616 }
4eb68604 4617 } elsif ($opt =~ m/^usb\d+/) {
f745762b
DC
4618 die "skip\n";
4619 # since we cannot reliably hot unplug usb devices
4620 # we are disabling it
4eb68604
DC
4621 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4622 vm_deviceunplug($vmid, $conf, $opt);
8edc9c08 4623 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4624 die "skip\n" if !$hotplug_features->{cpu};
8edc9c08 4625 qemu_cpu_hotplug($vmid, $conf, undef);
9c2f7069 4626 } elsif ($opt eq 'balloon') {
81d95ae1 4627 # enable balloon device is not hotpluggable
75b51053
DC
4628 die "skip\n" if defined($conf->{balloon}) && $conf->{balloon} == 0;
4629 # here we reset the ballooning value to memory
4630 my $balloon = $conf->{memory} || $defaults->{memory};
4631 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
81d95ae1
DM
4632 } elsif ($fast_plug_option->{$opt}) {
4633 # do nothing
3eec5767 4634 } elsif ($opt =~ m/^net(\d+)$/) {
b3c2bdd1 4635 die "skip\n" if !$hotplug_features->{network};
3eec5767 4636 vm_deviceunplug($vmid, $conf, $opt);
74479ee9 4637 } elsif (is_valid_drivename($opt)) {
b3c2bdd1 4638 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
19120f99 4639 vm_deviceunplug($vmid, $conf, $opt);
3dc38fbb 4640 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4d3f29ed
AD
4641 } elsif ($opt =~ m/^memory$/) {
4642 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4643 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
c8effec3
AD
4644 } elsif ($opt eq 'cpuunits') {
4645 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
58be00f1
AD
4646 } elsif ($opt eq 'cpulimit') {
4647 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3d7389fe 4648 } else {
e56beeda 4649 die "skip\n";
3d7389fe 4650 }
3a11fadb
DM
4651 };
4652 if (my $err = $@) {
e56beeda
DM
4653 &$add_error($opt, $err) if $err ne "skip\n";
4654 } else {
3a11fadb
DM
4655 # save new config if hotplug was successful
4656 delete $conf->{$opt};
4657 vmconfig_undelete_pending_option($conf, $opt);
ffda963f
FG
4658 PVE::QemuConfig->write_config($vmid, $conf);
4659 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4660 }
3d7389fe
DM
4661 }
4662
9ed7a77c
WB
4663 my $apply_pending_cloudinit;
4664 $apply_pending_cloudinit = sub {
4665 my ($key, $value) = @_;
4666 $apply_pending_cloudinit = sub {}; # once is enough
4667
4668 my @cloudinit_opts = keys %$confdesc_cloudinit;
4669 foreach my $opt (keys %{$conf->{pending}}) {
4670 next if !grep { $_ eq $opt } @cloudinit_opts;
4671 $conf->{$opt} = delete $conf->{pending}->{$opt};
4672 }
4673
4674 my $new_conf = { %$conf };
4675 $new_conf->{$key} = $value;
4676 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($new_conf, $vmid);
4677 };
4678
3d7389fe 4679 foreach my $opt (keys %{$conf->{pending}}) {
3a11fadb 4680 next if $selection && !$selection->{$opt};
3d7389fe 4681 my $value = $conf->{pending}->{$opt};
3a11fadb 4682 eval {
51a6f637
AD
4683 if ($opt eq 'hotplug') {
4684 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4685 } elsif ($opt eq 'tablet') {
b3c2bdd1 4686 die "skip\n" if !$hotplug_features->{usb};
3a11fadb 4687 if ($value == 1) {
d559309f
WB
4688 vm_deviceplug($storecfg, $conf, $vmid, 'tablet', $arch, $machine_type);
4689 vm_deviceplug($storecfg, $conf, $vmid, 'keyboard', $arch, $machine_type)
4690 if $arch eq 'aarch64';
3a11fadb 4691 } elsif ($value == 0) {
d559309f
WB
4692 vm_deviceunplug($vmid, $conf, 'tablet');
4693 vm_deviceunplug($vmid, $conf, 'keyboard') if $arch eq 'aarch64';
3a11fadb 4694 }
4eb68604 4695 } elsif ($opt =~ m/^usb\d+$/) {
f745762b
DC
4696 die "skip\n";
4697 # since we cannot reliably hot unplug usb devices
4698 # we are disabling it
4eb68604
DC
4699 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4700 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4701 die "skip\n" if !$d;
d559309f 4702 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d, $arch, $machine_type);
8edc9c08 4703 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4704 die "skip\n" if !$hotplug_features->{cpu};
3a11fadb
DM
4705 qemu_cpu_hotplug($vmid, $conf, $value);
4706 } elsif ($opt eq 'balloon') {
81d95ae1 4707 # enable/disable balloning device is not hotpluggable
8fe689e7 4708 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
a1b7d579 4709 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
81d95ae1
DM
4710 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4711
3a11fadb 4712 # allow manual ballooning if shares is set to zero
4cc1efa6 4713 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
9c2f7069
AD
4714 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4715 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4716 }
a1b7d579 4717 } elsif ($opt =~ m/^net(\d+)$/) {
3eec5767 4718 # some changes can be done without hotplug
a1b7d579 4719 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
d559309f 4720 $vmid, $opt, $value, $arch, $machine_type);
74479ee9 4721 } elsif (is_valid_drivename($opt)) {
a05cff86 4722 # some changes can be done without hotplug
9ed7a77c
WB
4723 my $drive = parse_drive($opt, $value);
4724 if (drive_is_cloudinit($drive)) {
4725 &$apply_pending_cloudinit($opt, $value);
4726 }
b3c2bdd1 4727 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
d559309f 4728 $vmid, $opt, $value, 1, $arch, $machine_type);
4d3f29ed
AD
4729 } elsif ($opt =~ m/^memory$/) { #dimms
4730 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4731 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
c8effec3
AD
4732 } elsif ($opt eq 'cpuunits') {
4733 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
58be00f1 4734 } elsif ($opt eq 'cpulimit') {
c6f773b8 4735 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
58be00f1 4736 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
3a11fadb 4737 } else {
e56beeda 4738 die "skip\n"; # skip non-hot-pluggable options
3d7389fe 4739 }
3a11fadb
DM
4740 };
4741 if (my $err = $@) {
e56beeda
DM
4742 &$add_error($opt, $err) if $err ne "skip\n";
4743 } else {
3a11fadb
DM
4744 # save new config if hotplug was successful
4745 $conf->{$opt} = $value;
4746 delete $conf->{pending}->{$opt};
ffda963f
FG
4747 PVE::QemuConfig->write_config($vmid, $conf);
4748 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4749 }
3d7389fe 4750 }
c427973b 4751}
055d554d 4752
3dc38fbb
WB
4753sub try_deallocate_drive {
4754 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4755
4756 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4757 my $volid = $drive->{file};
4758 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4759 my $sid = PVE::Storage::parse_volume_id($volid);
4760 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
cee01bcb
WB
4761
4762 # check if the disk is really unused
cee01bcb 4763 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
77019edf 4764 if is_volume_in_use($storecfg, $conf, $key, $volid);
cee01bcb 4765 PVE::Storage::vdisk_free($storecfg, $volid);
3dc38fbb 4766 return 1;
40b977f3
WL
4767 } else {
4768 # If vm is not owner of this disk remove from config
4769 return 1;
3dc38fbb
WB
4770 }
4771 }
4772
4773 return undef;
4774}
4775
4776sub vmconfig_delete_or_detach_drive {
4777 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4778
4779 my $drive = parse_drive($opt, $conf->{$opt});
4780
4781 my $rpcenv = PVE::RPCEnvironment::get();
4782 my $authuser = $rpcenv->get_user();
4783
4784 if ($force) {
4785 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4786 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4787 } else {
4788 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4789 }
4790}
4791
055d554d 4792sub vmconfig_apply_pending {
3a11fadb 4793 my ($vmid, $conf, $storecfg) = @_;
c427973b
DM
4794
4795 # cold plug
055d554d 4796
3dc38fbb
WB
4797 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4798 while (my ($opt, $force) = each %$pending_delete_hash) {
055d554d 4799 die "internal error" if $opt =~ m/^unused/;
ffda963f 4800 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4801 if (!defined($conf->{$opt})) {
4802 vmconfig_undelete_pending_option($conf, $opt);
ffda963f 4803 PVE::QemuConfig->write_config($vmid, $conf);
74479ee9 4804 } elsif (is_valid_drivename($opt)) {
3dc38fbb 4805 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
055d554d
DM
4806 vmconfig_undelete_pending_option($conf, $opt);
4807 delete $conf->{$opt};
ffda963f 4808 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4809 } else {
4810 vmconfig_undelete_pending_option($conf, $opt);
4811 delete $conf->{$opt};
ffda963f 4812 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4813 }
4814 }
4815
ffda963f 4816 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4817
4818 foreach my $opt (keys %{$conf->{pending}}) { # add/change
ffda963f 4819 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4820
4821 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4822 # skip if nothing changed
74479ee9 4823 } elsif (is_valid_drivename($opt)) {
055d554d
DM
4824 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4825 if defined($conf->{$opt});
4826 $conf->{$opt} = $conf->{pending}->{$opt};
4827 } else {
4828 $conf->{$opt} = $conf->{pending}->{$opt};
4829 }
4830
4831 delete $conf->{pending}->{$opt};
ffda963f 4832 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4833 }
4834}
4835
3eec5767
DM
4836my $safe_num_ne = sub {
4837 my ($a, $b) = @_;
4838
4839 return 0 if !defined($a) && !defined($b);
4840 return 1 if !defined($a);
4841 return 1 if !defined($b);
4842
4843 return $a != $b;
4844};
4845
4846my $safe_string_ne = sub {
4847 my ($a, $b) = @_;
4848
4849 return 0 if !defined($a) && !defined($b);
4850 return 1 if !defined($a);
4851 return 1 if !defined($b);
4852
4853 return $a ne $b;
4854};
4855
4856sub vmconfig_update_net {
d559309f 4857 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $arch, $machine_type) = @_;
3eec5767
DM
4858
4859 my $newnet = parse_net($value);
4860
4861 if ($conf->{$opt}) {
4862 my $oldnet = parse_net($conf->{$opt});
4863
4864 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4865 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4866 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4867 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4868
4869 # for non online change, we try to hot-unplug
7196b757 4870 die "skip\n" if !$hotplug;
3eec5767
DM
4871 vm_deviceunplug($vmid, $conf, $opt);
4872 } else {
4873
4874 die "internal error" if $opt !~ m/net(\d+)/;
4875 my $iface = "tap${vmid}i$1";
a1b7d579 4876
25088687
DM
4877 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4878 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
16d08ecf 4879 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
25088687 4880 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
3eec5767 4881 PVE::Network::tap_unplug($iface);
4f4fbeb0
WB
4882 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4883 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4884 # Rate can be applied on its own but any change above needs to
4885 # include the rate in tap_plug since OVS resets everything.
4886 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
3eec5767 4887 }
38c590d9 4888
25088687
DM
4889 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4890 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4891 }
4892
38c590d9 4893 return 1;
3eec5767
DM
4894 }
4895 }
a1b7d579 4896
7196b757 4897 if ($hotplug) {
d559309f 4898 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet, $arch, $machine_type);
38c590d9
DM
4899 } else {
4900 die "skip\n";
4901 }
3eec5767
DM
4902}
4903
a05cff86 4904sub vmconfig_update_disk {
d559309f 4905 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force, $arch, $machine_type) = @_;
a05cff86
DM
4906
4907 # fixme: do we need force?
4908
4909 my $drive = parse_drive($opt, $value);
4910
4911 if ($conf->{$opt}) {
4912
4913 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4914
4915 my $media = $drive->{media} || 'disk';
4916 my $oldmedia = $old_drive->{media} || 'disk';
4917 die "unable to change media type\n" if $media ne $oldmedia;
4918
4919 if (!drive_is_cdrom($old_drive)) {
4920
a1b7d579 4921 if ($drive->{file} ne $old_drive->{file}) {
a05cff86 4922
7196b757 4923 die "skip\n" if !$hotplug;
a05cff86
DM
4924
4925 # unplug and register as unused
4926 vm_deviceunplug($vmid, $conf, $opt);
4927 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
a1b7d579 4928
a05cff86
DM
4929 } else {
4930 # update existing disk
4931
4932 # skip non hotpluggable value
6ecfbb44 4933 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
22de899a 4934 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
6e11f143 4935 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
a05cff86
DM
4936 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4937 die "skip\n";
4938 }
4939
4940 # apply throttle
4941 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4942 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4943 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4944 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4945 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4946 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4947 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4948 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4949 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4950 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4951 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
9196a8ec
WB
4952 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4953 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4954 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4955 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4956 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4957 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4958 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
a1b7d579 4959
a05cff86
DM
4960 qemu_block_set_io_throttle($vmid,"drive-$opt",
4961 ($drive->{mbps} || 0)*1024*1024,
4962 ($drive->{mbps_rd} || 0)*1024*1024,
4963 ($drive->{mbps_wr} || 0)*1024*1024,
4964 $drive->{iops} || 0,
4965 $drive->{iops_rd} || 0,
4966 $drive->{iops_wr} || 0,
4967 ($drive->{mbps_max} || 0)*1024*1024,
4968 ($drive->{mbps_rd_max} || 0)*1024*1024,
4969 ($drive->{mbps_wr_max} || 0)*1024*1024,
4970 $drive->{iops_max} || 0,
4971 $drive->{iops_rd_max} || 0,
9196a8ec
WB
4972 $drive->{iops_wr_max} || 0,
4973 $drive->{bps_max_length} || 1,
4974 $drive->{bps_rd_max_length} || 1,
4975 $drive->{bps_wr_max_length} || 1,
4976 $drive->{iops_max_length} || 1,
4977 $drive->{iops_rd_max_length} || 1,
4978 $drive->{iops_wr_max_length} || 1);
a05cff86
DM
4979
4980 }
a1b7d579 4981
a05cff86
DM
4982 return 1;
4983 }
4de1bb25
DM
4984
4985 } else { # cdrom
a1b7d579 4986
4de1bb25
DM
4987 if ($drive->{file} eq 'none') {
4988 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
2d9ddec5
WB
4989 if (drive_is_cloudinit($old_drive)) {
4990 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive);
4991 }
4de1bb25
DM
4992 } else {
4993 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4994 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4995 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4996 }
a1b7d579 4997
34758d66 4998 return 1;
a05cff86
DM
4999 }
5000 }
5001 }
5002
a1b7d579 5003 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4de1bb25 5004 # hotplug new disks
f7b4356f 5005 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
d559309f 5006 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive, $arch, $machine_type);
a05cff86
DM
5007}
5008
1e3baf05 5009sub vm_start {
ba9e1000 5010 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
2189246c 5011 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
1e3baf05 5012
ffda963f
FG
5013 PVE::QemuConfig->lock_config($vmid, sub {
5014 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
1e3baf05 5015
ffda963f 5016 die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
3dcb98d5 5017
ffda963f 5018 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 5019
7e8dcf2c 5020 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 5021
055d554d 5022 if (!$statefile && scalar(keys %{$conf->{pending}})) {
3a11fadb 5023 vmconfig_apply_pending($vmid, $conf, $storecfg);
ffda963f 5024 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
5025 }
5026
0c9a7596
AD
5027 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
5028
6c47d546
DM
5029 my $defaults = load_defaults();
5030
5031 # set environment variable useful inside network script
5032 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
5033
2189246c
AD
5034 my $local_volumes = {};
5035
3b4cf0f0 5036 if ($targetstorage) {
2189246c
AD
5037 foreach_drive($conf, sub {
5038 my ($ds, $drive) = @_;
5039
5040 return if drive_is_cdrom($drive);
5041
5042 my $volid = $drive->{file};
5043
5044 return if !$volid;
5045
5046 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
5047
5048 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
5049 return if $scfg->{shared};
5050 $local_volumes->{$ds} = [$volid, $storeid, $volname];
5051 });
5052
5053 my $format = undef;
5054
5055 foreach my $opt (sort keys %$local_volumes) {
5056
5057 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
5058 my $drive = parse_drive($opt, $conf->{$opt});
5059
5060 #if remote storage is specified, use default format
5061 if ($targetstorage && $targetstorage ne "1") {
5062 $storeid = $targetstorage;
5063 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
5064 $format = $defFormat;
5065 } else {
5066 #else we use same format than original
5067 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
5068 $format = qemu_img_format($scfg, $volid);
5069 }
5070
5071 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
5072 my $newdrive = $drive;
5073 $newdrive->{format} = $format;
5074 $newdrive->{file} = $newvolid;
5075 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
5076 $local_volumes->{$opt} = $drivestr;
5077 #pass drive to conf for command line
5078 $conf->{$opt} = $drivestr;
5079 }
5080 }
5081
67812f9c 5082 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 5083
1e3baf05 5084 my $migrate_port = 0;
5bc1e039 5085 my $migrate_uri;
1e3baf05
DM
5086 if ($statefile) {
5087 if ($statefile eq 'tcp') {
5bc1e039
SP
5088 my $localip = "localhost";
5089 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
af0eba7e 5090 my $nodename = PVE::INotify::nodename();
2de2d6f7 5091
b7a5a225
TL
5092 if (!defined($migration_type)) {
5093 if (defined($datacenterconf->{migration}->{type})) {
5094 $migration_type = $datacenterconf->{migration}->{type};
5095 } else {
5096 $migration_type = 'secure';
5097 }
5098 }
5099
2de2d6f7
TL
5100 if ($migration_type eq 'insecure') {
5101 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
5102 if ($migrate_network_addr) {
5103 $localip = $migrate_network_addr;
5104 } else {
5bc1e039 5105 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
2de2d6f7
TL
5106 }
5107
5108 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5bc1e039 5109 }
2de2d6f7 5110
af0eba7e
WB
5111 my $pfamily = PVE::Tools::get_host_address_family($nodename);
5112 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
407e0b8b 5113 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
5114 push @$cmd, '-incoming', $migrate_uri;
5115 push @$cmd, '-S';
1c9d54bf
TL
5116
5117 } elsif ($statefile eq 'unix') {
5118 # should be default for secure migrations as a ssh TCP forward
5119 # tunnel is not deterministic reliable ready and fails regurarly
5120 # to set up in time, so use UNIX socket forwards
54323eed
TL
5121 my $socket_addr = "/run/qemu-server/$vmid.migrate";
5122 unlink $socket_addr;
5123
5124 $migrate_uri = "unix:$socket_addr";
1c9d54bf
TL
5125
5126 push @$cmd, '-incoming', $migrate_uri;
5127 push @$cmd, '-S';
5128
1e3baf05 5129 } else {
6c47d546 5130 push @$cmd, '-loadstate', $statefile;
1e3baf05 5131 }
91bd6c90
DM
5132 } elsif ($paused) {
5133 push @$cmd, '-S';
1e3baf05
DM
5134 }
5135
1e3baf05 5136 # host pci devices
040b06b7
DA
5137 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
5138 my $d = parse_hostpci($conf->{"hostpci$i"});
5139 next if !$d;
b1f72af6
AD
5140 my $pcidevices = $d->{pciid};
5141 foreach my $pcidevice (@$pcidevices) {
5142 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
000fc0a2 5143
b71351a7
DC
5144 my $info = PVE::SysFSTools::pci_device_info("0000:$pciid");
5145 die "IOMMU not present\n" if !PVE::SysFSTools::check_iommu_support();
b1f72af6 5146 die "no pci device info for device '$pciid'\n" if !$info;
b71351a7
DC
5147 die "can't unbind/bind pci group to vfio '$pciid'\n"
5148 if !PVE::SysFSTools::pci_dev_group_bind_to_vfio($pciid);
5149 die "can't reset pci device '$pciid'\n"
5150 if $info->{has_fl_reset} and !PVE::SysFSTools::pci_dev_reset($info);
b1f72af6 5151 }
040b06b7 5152 }
1e3baf05
DM
5153
5154 PVE::Storage::activate_volumes($storecfg, $vollist);
5155
3c23aa80
WB
5156 if (!check_running($vmid, 1)) {
5157 eval {
5158 run_command(['/bin/systemctl', 'stop', "$vmid.scope"],
5159 outfunc => sub {}, errfunc => sub {});
5160 };
2b401189
AD
5161 }
5162
8e59d952
WB
5163 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
5164 : $defaults->{cpuunits};
5165
f38de678
AD
5166 my $start_timeout = $conf->{hugepages} ? 300 : 30;
5167 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
7023f3ea
AD
5168
5169 my %properties = (
5170 Slice => 'qemu.slice',
5171 KillMode => 'none',
5172 CPUShares => $cpuunits
5173 );
5174
5175 if (my $cpulimit = $conf->{cpulimit}) {
5176 $properties{CPUQuota} = int($cpulimit * 100);
5177 }
5178 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
5179
503308ed
WB
5180 my $run_qemu = sub {
5181 PVE::Tools::run_fork sub {
d04d6af1 5182 PVE::Systemd::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
503308ed
WB
5183 run_command($cmd, %run_params);
5184 };
5185 };
5186
7023f3ea
AD
5187 if ($conf->{hugepages}) {
5188
5189 my $code = sub {
5190 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
5191 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
5192
5193 PVE::QemuServer::Memory::hugepages_mount();
5194 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
5195
503308ed 5196 eval { $run_qemu->() };
7023f3ea
AD
5197 if (my $err = $@) {
5198 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
5199 die $err;
5200 }
5201
5202 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
5203 };
5204 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
5205
5206 } else {
503308ed 5207 eval { $run_qemu->() };
7023f3ea 5208 }
77cde36b
DC
5209
5210 if (my $err = $@) {
5211 # deactivate volumes if start fails
5212 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
5213 die "start failed: $err";
5214 }
1e3baf05 5215
5bc1e039 5216 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 5217
b37ecfe6 5218 if ($statefile && $statefile ne 'tcp' && $statefile ne 'unix') {
95381ce0 5219 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 5220 warn $@ if $@;
62de2cbd
DM
5221 }
5222
2189246c
AD
5223 #start nbd server for storage migration
5224 if ($targetstorage) {
2189246c
AD
5225 my $nodename = PVE::INotify::nodename();
5226 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
5227 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
5228 my $pfamily = PVE::Tools::get_host_address_family($nodename);
5229 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
5230
5231 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet', data => { host => "${localip}", port => "${migrate_port}" } } );
5232
5233 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5234
5235 foreach my $opt (sort keys %$local_volumes) {
5236 my $volid = $local_volumes->{$opt};
5237 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
5238 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
5239 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
5240 }
5241 }
5242
1d794448 5243 if ($migratedfrom) {
a89fded1 5244 eval {
8e90138a 5245 set_migration_caps($vmid);
a89fded1 5246 };
1d794448 5247 warn $@ if $@;
a89fded1 5248
1d794448
DM
5249 if ($spice_port) {
5250 print "spice listens on port $spice_port\n";
5251 if ($spice_ticket) {
8e90138a
DM
5252 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
5253 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
5254 }
5255 }
5256
1d794448 5257 } else {
51153f86
DC
5258 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
5259 if !$statefile && $conf->{balloon};
25088687
DM
5260
5261 foreach my $opt (keys %$conf) {
5262 next if $opt !~ m/^net\d+$/;
5263 my $nicconf = parse_net($conf->{$opt});
5264 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
5265 }
e18b0b99 5266 }
a1b7d579 5267
eb065317
AD
5268 vm_mon_cmd_nocheck($vmid, 'qom-set',
5269 path => "machine/peripheral/balloon0",
5270 property => "guest-stats-polling-interval",
5271 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
5272
1e3baf05
DM
5273 });
5274}
5275
0eedc444
AD
5276sub vm_mon_cmd {
5277 my ($vmid, $execute, %params) = @_;
5278
26f11676
DM
5279 my $cmd = { execute => $execute, arguments => \%params };
5280 vm_qmp_command($vmid, $cmd);
0eedc444
AD
5281}
5282
5283sub vm_mon_cmd_nocheck {
5284 my ($vmid, $execute, %params) = @_;
5285
26f11676
DM
5286 my $cmd = { execute => $execute, arguments => \%params };
5287 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
5288}
5289
c971c4f2 5290sub vm_qmp_command {
c5a07de5 5291 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 5292
c971c4f2 5293 my $res;
26f11676 5294
14db5366
DM
5295 my $timeout;
5296 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
5297 $timeout = $cmd->{arguments}->{timeout};
5298 delete $cmd->{arguments}->{timeout};
5299 }
be190583 5300
c971c4f2
AD
5301 eval {
5302 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
7a6c2150
DM
5303 my $sname = qmp_socket($vmid);
5304 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
c5a07de5 5305 my $qmpclient = PVE::QMPClient->new();
dab36e1e 5306
14db5366 5307 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
dab36e1e
DM
5308 } else {
5309 die "unable to open monitor socket\n";
5310 }
c971c4f2 5311 };
26f11676 5312 if (my $err = $@) {
c971c4f2
AD
5313 syslog("err", "VM $vmid qmp command failed - $err");
5314 die $err;
5315 }
5316
5317 return $res;
5318}
5319
9df5cbcc
DM
5320sub vm_human_monitor_command {
5321 my ($vmid, $cmdline) = @_;
5322
5323 my $res;
5324
f5eb281a 5325 my $cmd = {
9df5cbcc
DM
5326 execute => 'human-monitor-command',
5327 arguments => { 'command-line' => $cmdline},
5328 };
5329
5330 return vm_qmp_command($vmid, $cmd);
5331}
5332
1e3baf05
DM
5333sub vm_commandline {
5334 my ($storecfg, $vmid) = @_;
5335
ffda963f 5336 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05
DM
5337
5338 my $defaults = load_defaults();
5339
6b64503e 5340 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 5341
5930c1ff 5342 return PVE::Tools::cmd2string($cmd);
1e3baf05
DM
5343}
5344
5345sub vm_reset {
5346 my ($vmid, $skiplock) = @_;
5347
ffda963f 5348 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5349
ffda963f 5350 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5351
ffda963f 5352 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 5353
816e2c4a 5354 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
5355 });
5356}
5357
5358sub get_vm_volumes {
5359 my ($conf) = @_;
1e3baf05 5360
ff1a2432 5361 my $vollist = [];
d5769dc2 5362 foreach_volid($conf, sub {
392f8b5d 5363 my ($volid, $attr) = @_;
ff1a2432 5364
d5769dc2 5365 return if $volid =~ m|^/|;
ff1a2432 5366
d5769dc2
DM
5367 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
5368 return if !$sid;
ff1a2432
DM
5369
5370 push @$vollist, $volid;
1e3baf05 5371 });
ff1a2432
DM
5372
5373 return $vollist;
5374}
5375
5376sub vm_stop_cleanup {
70b04821 5377 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
ff1a2432 5378
745fed70 5379 eval {
ff1a2432 5380
254575e9
DM
5381 if (!$keepActive) {
5382 my $vollist = get_vm_volumes($conf);
5383 PVE::Storage::deactivate_volumes($storecfg, $vollist);
5384 }
a1b7d579 5385
ab6a046f 5386 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
5387 unlink "/var/run/qemu-server/${vmid}.$ext";
5388 }
a1b7d579 5389
70b04821 5390 vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
745fed70
DM
5391 };
5392 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
5393}
5394
e6c3b671 5395# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
5396# We need that when migration VMs to other nodes (files already moved)
5397# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 5398sub vm_stop {
af30308f 5399 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 5400
9269013a 5401 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 5402
af30308f
DM
5403 if ($migratedfrom){
5404 my $pid = check_running($vmid, $nocheck, $migratedfrom);
5405 kill 15, $pid if $pid;
ffda963f 5406 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
70b04821 5407 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
af30308f
DM
5408 return;
5409 }
5410
ffda963f 5411 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5412
e6c3b671 5413 my $pid = check_running($vmid, $nocheck);
ff1a2432 5414 return if !$pid;
1e3baf05 5415
ff1a2432 5416 my $conf;
e6c3b671 5417 if (!$nocheck) {
ffda963f
FG
5418 $conf = PVE::QemuConfig->load_config($vmid);
5419 PVE::QemuConfig->check_lock($conf) if !$skiplock;
7f4a5b5a 5420 if (!defined($timeout) && $shutdown && $conf->{startup}) {
38f7f26c 5421 my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
7f4a5b5a
DM
5422 $timeout = $opts->{down} if $opts->{down};
5423 }
e6c3b671 5424 }
19672434 5425
7f4a5b5a 5426 $timeout = 60 if !defined($timeout);
67fb9de6 5427
9269013a
DM
5428 eval {
5429 if ($shutdown) {
9d66b397 5430 if (defined($conf) && parse_guest_agent($conf)->{enabled}) {
2ea54503 5431 vm_qmp_command($vmid, { execute => "guest-shutdown" }, $nocheck);
1c0c1c17 5432 } else {
2ea54503 5433 vm_qmp_command($vmid, { execute => "system_powerdown" }, $nocheck);
1c0c1c17 5434 }
9269013a 5435 } else {
2ea54503 5436 vm_qmp_command($vmid, { execute => "quit" }, $nocheck);
afdb31d5 5437 }
9269013a 5438 };
1e3baf05
DM
5439 my $err = $@;
5440
5441 if (!$err) {
1e3baf05 5442 my $count = 0;
e6c3b671 5443 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
5444 $count++;
5445 sleep 1;
5446 }
5447
5448 if ($count >= $timeout) {
9269013a
DM
5449 if ($force) {
5450 warn "VM still running - terminating now with SIGTERM\n";
5451 kill 15, $pid;
5452 } else {
5453 die "VM quit/powerdown failed - got timeout\n";
5454 }
5455 } else {
70b04821 5456 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
9269013a 5457 return;
1e3baf05
DM
5458 }
5459 } else {
9269013a
DM
5460 if ($force) {
5461 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5462 kill 15, $pid;
5463 } else {
afdb31d5 5464 die "VM quit/powerdown failed\n";
9269013a 5465 }
1e3baf05
DM
5466 }
5467
5468 # wait again
ff1a2432 5469 $timeout = 10;
1e3baf05
DM
5470
5471 my $count = 0;
e6c3b671 5472 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
5473 $count++;
5474 sleep 1;
5475 }
5476
5477 if ($count >= $timeout) {
ff1a2432 5478 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 5479 kill 9, $pid;
ff1a2432 5480 sleep 1;
1e3baf05
DM
5481 }
5482
70b04821 5483 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
ff1a2432 5484 });
1e3baf05
DM
5485}
5486
5487sub vm_suspend {
5488 my ($vmid, $skiplock) = @_;
5489
ffda963f 5490 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5491
ffda963f 5492 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5493
e79706d4
FG
5494 PVE::QemuConfig->check_lock($conf)
5495 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
bcb7c9cf 5496
f77f91f3 5497 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
5498 });
5499}
5500
5501sub vm_resume {
289e0b85 5502 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 5503
ffda963f 5504 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5505
c2786bed
DC
5506 my $res = vm_mon_cmd($vmid, 'query-status');
5507 my $resume_cmd = 'cont';
5508
5509 if ($res->{status} && $res->{status} eq 'suspended') {
5510 $resume_cmd = 'system_wakeup';
5511 }
5512
289e0b85 5513 if (!$nocheck) {
1e3baf05 5514
ffda963f 5515 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5516
e79706d4
FG
5517 PVE::QemuConfig->check_lock($conf)
5518 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
289e0b85 5519
c2786bed 5520 vm_mon_cmd($vmid, $resume_cmd);
289e0b85
AD
5521
5522 } else {
c2786bed 5523 vm_mon_cmd_nocheck($vmid, $resume_cmd);
289e0b85 5524 }
1e3baf05
DM
5525 });
5526}
5527
5fdbe4f0
DM
5528sub vm_sendkey {
5529 my ($vmid, $skiplock, $key) = @_;
1e3baf05 5530
ffda963f 5531 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5532
ffda963f 5533 my $conf = PVE::QemuConfig->load_config($vmid);
f5eb281a 5534
7b7c6d1b
DM
5535 # there is no qmp command, so we use the human monitor command
5536 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
5537 });
5538}
5539
5540sub vm_destroy {
5541 my ($storecfg, $vmid, $skiplock) = @_;
5542
ffda963f 5543 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5544
ffda963f 5545 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5546
ff1a2432 5547 if (!check_running($vmid)) {
15cc8784 5548 destroy_vm($storecfg, $vmid, undef, $skiplock);
ff1a2432
DM
5549 } else {
5550 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
5551 }
5552 });
5553}
5554
3e16d5fc
DM
5555# vzdump restore implementaion
5556
ed221350 5557sub tar_archive_read_firstfile {
3e16d5fc 5558 my $archive = shift;
afdb31d5 5559
3e16d5fc
DM
5560 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
5561
5562 # try to detect archive type first
387ba257 5563 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
3e16d5fc 5564 die "unable to open file '$archive'\n";
387ba257 5565 my $firstfile = <$fh>;
3e16d5fc 5566 kill 15, $pid;
387ba257 5567 close $fh;
3e16d5fc
DM
5568
5569 die "ERROR: archive contaions no data\n" if !$firstfile;
5570 chomp $firstfile;
5571
5572 return $firstfile;
5573}
5574
ed221350
DM
5575sub tar_restore_cleanup {
5576 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
5577
5578 print STDERR "starting cleanup\n";
5579
5580 if (my $fd = IO::File->new($statfile, "r")) {
5581 while (defined(my $line = <$fd>)) {
5582 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5583 my $volid = $2;
5584 eval {
5585 if ($volid =~ m|^/|) {
5586 unlink $volid || die 'unlink failed\n';
5587 } else {
ed221350 5588 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 5589 }
afdb31d5 5590 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
5591 };
5592 print STDERR "unable to cleanup '$volid' - $@" if $@;
5593 } else {
5594 print STDERR "unable to parse line in statfile - $line";
afdb31d5 5595 }
3e16d5fc
DM
5596 }
5597 $fd->close();
5598 }
5599}
5600
5601sub restore_archive {
a0d1b1a2 5602 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 5603
91bd6c90
DM
5604 my $format = $opts->{format};
5605 my $comp;
5606
5607 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5608 $format = 'tar' if !$format;
5609 $comp = 'gzip';
5610 } elsif ($archive =~ m/\.tar$/) {
5611 $format = 'tar' if !$format;
5612 } elsif ($archive =~ m/.tar.lzo$/) {
5613 $format = 'tar' if !$format;
5614 $comp = 'lzop';
5615 } elsif ($archive =~ m/\.vma$/) {
5616 $format = 'vma' if !$format;
5617 } elsif ($archive =~ m/\.vma\.gz$/) {
5618 $format = 'vma' if !$format;
5619 $comp = 'gzip';
5620 } elsif ($archive =~ m/\.vma\.lzo$/) {
5621 $format = 'vma' if !$format;
5622 $comp = 'lzop';
5623 } else {
5624 $format = 'vma' if !$format; # default
5625 }
5626
5627 # try to detect archive format
5628 if ($format eq 'tar') {
5629 return restore_tar_archive($archive, $vmid, $user, $opts);
5630 } else {
5631 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
5632 }
5633}
5634
5635sub restore_update_config_line {
5636 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5637
5638 return if $line =~ m/^\#qmdump\#/;
5639 return if $line =~ m/^\#vzdump\#/;
5640 return if $line =~ m/^lock:/;
5641 return if $line =~ m/^unused\d+:/;
5642 return if $line =~ m/^parent:/;
ca3e4fa4 5643 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90 5644
b5b99790 5645 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
91bd6c90
DM
5646 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5647 # try to convert old 1.X settings
5648 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5649 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
5650 my ($model, $macaddr) = split(/\=/, $devconfig);
b5b99790 5651 $macaddr = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if !$macaddr || $unique;
91bd6c90
DM
5652 my $net = {
5653 model => $model,
5654 bridge => "vmbr$ind",
5655 macaddr => $macaddr,
5656 };
5657 my $netstr = print_net($net);
5658
5659 print $outfd "net$cookie->{netcount}: $netstr\n";
5660 $cookie->{netcount}++;
5661 }
5662 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5663 my ($id, $netstr) = ($1, $2);
5664 my $net = parse_net($netstr);
b5b99790 5665 $net->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if $net->{macaddr};
91bd6c90
DM
5666 $netstr = print_net($net);
5667 print $outfd "$id: $netstr\n";
6470743f 5668 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
91bd6c90 5669 my $virtdev = $1;
907ea891 5670 my $value = $3;
d9faf790
WB
5671 my $di = parse_drive($virtdev, $value);
5672 if (defined($di->{backup}) && !$di->{backup}) {
91bd6c90 5673 print $outfd "#$line";
c0f7406e 5674 } elsif ($map->{$virtdev}) {
8fd57431 5675 delete $di->{format}; # format can change on restore
91bd6c90 5676 $di->{file} = $map->{$virtdev};
ed221350 5677 $value = print_drive($vmid, $di);
91bd6c90
DM
5678 print $outfd "$virtdev: $value\n";
5679 } else {
5680 print $outfd $line;
5681 }
1a0c2f03 5682 } elsif (($line =~ m/^vmgenid: (.*)/)) {
babecffe 5683 my $vmgenid = $1;
6ee499ff 5684 if ($vmgenid ne '0') {
1a0c2f03 5685 # always generate a new vmgenid if there was a valid one setup
6ee499ff
DC
5686 $vmgenid = generate_uuid();
5687 }
1a0c2f03 5688 print $outfd "vmgenid: $vmgenid\n";
19a5dd55
WL
5689 } elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
5690 my ($uuid, $uuid_str);
5691 UUID::generate($uuid);
5692 UUID::unparse($uuid, $uuid_str);
5693 my $smbios1 = parse_smbios1($2);
5694 $smbios1->{uuid} = $uuid_str;
5695 print $outfd $1.print_smbios1($smbios1)."\n";
91bd6c90
DM
5696 } else {
5697 print $outfd $line;
5698 }
5699}
5700
5701sub scan_volids {
5702 my ($cfg, $vmid) = @_;
5703
5704 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
5705
5706 my $volid_hash = {};
5707 foreach my $storeid (keys %$info) {
5708 foreach my $item (@{$info->{$storeid}}) {
5709 next if !($item->{volid} && $item->{size});
5996a936 5710 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
5711 $volid_hash->{$item->{volid}} = $item;
5712 }
5713 }
5714
5715 return $volid_hash;
5716}
5717
77019edf
WB
5718sub is_volume_in_use {
5719 my ($storecfg, $conf, $skip_drive, $volid) = @_;
a8e2f942 5720
77019edf 5721 my $path = PVE::Storage::path($storecfg, $volid);
a8e2f942
DM
5722
5723 my $scan_config = sub {
5724 my ($cref, $snapname) = @_;
5725
5726 foreach my $key (keys %$cref) {
5727 my $value = $cref->{$key};
74479ee9 5728 if (is_valid_drivename($key)) {
a8e2f942
DM
5729 next if $skip_drive && $key eq $skip_drive;
5730 my $drive = parse_drive($key, $value);
5731 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
77019edf 5732 return 1 if $volid eq $drive->{file};
a8e2f942 5733 if ($drive->{file} =~ m!^/!) {
77019edf 5734 return 1 if $drive->{file} eq $path;
a8e2f942
DM
5735 } else {
5736 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
5737 next if !$storeid;
5738 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
5739 next if !$scfg;
77019edf 5740 return 1 if $path eq PVE::Storage::path($storecfg, $drive->{file}, $snapname);
a8e2f942
DM
5741 }
5742 }
5743 }
77019edf
WB
5744
5745 return 0;
a8e2f942
DM
5746 };
5747
77019edf 5748 return 1 if &$scan_config($conf);
a8e2f942
DM
5749
5750 undef $skip_drive;
5751
77019edf
WB
5752 foreach my $snapname (keys %{$conf->{snapshots}}) {
5753 return 1 if &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
a8e2f942
DM
5754 }
5755
77019edf 5756 return 0;
a8e2f942
DM
5757}
5758
91bd6c90
DM
5759sub update_disksize {
5760 my ($vmid, $conf, $volid_hash) = @_;
be190583 5761
91bd6c90 5762 my $changes;
53b81297 5763 my $prefix = "VM $vmid:";
91bd6c90 5764
c449137a
DC
5765 # used and unused disks
5766 my $referenced = {};
91bd6c90 5767
5996a936
DM
5768 # Note: it is allowed to define multiple storages with same path (alias), so
5769 # we need to check both 'volid' and real 'path' (two different volid can point
5770 # to the same path).
5771
c449137a 5772 my $referencedpath = {};
be190583 5773
91bd6c90
DM
5774 # update size info
5775 foreach my $opt (keys %$conf) {
74479ee9 5776 if (is_valid_drivename($opt)) {
ed221350 5777 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
5778 my $volid = $drive->{file};
5779 next if !$volid;
5780
c449137a 5781 $referenced->{$volid} = 1;
be190583 5782 if ($volid_hash->{$volid} &&
5996a936 5783 (my $path = $volid_hash->{$volid}->{path})) {
c449137a 5784 $referencedpath->{$path} = 1;
5996a936 5785 }
91bd6c90 5786
ed221350 5787 next if drive_is_cdrom($drive);
91bd6c90
DM
5788 next if !$volid_hash->{$volid};
5789
5790 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
5791 my $new = print_drive($vmid, $drive);
5792 if ($new ne $conf->{$opt}) {
5793 $changes = 1;
5794 $conf->{$opt} = $new;
53b81297 5795 print "$prefix update disk '$opt' information.\n";
7a907ce6 5796 }
91bd6c90
DM
5797 }
5798 }
5799
5996a936
DM
5800 # remove 'unusedX' entry if volume is used
5801 foreach my $opt (keys %$conf) {
5802 next if $opt !~ m/^unused\d+$/;
5803 my $volid = $conf->{$opt};
5804 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
c449137a 5805 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
53b81297 5806 print "$prefix remove entry '$opt', its volume '$volid' is in use.\n";
5996a936
DM
5807 $changes = 1;
5808 delete $conf->{$opt};
5809 }
c449137a
DC
5810
5811 $referenced->{$volid} = 1;
5812 $referencedpath->{$path} = 1 if $path;
5996a936
DM
5813 }
5814
91bd6c90
DM
5815 foreach my $volid (sort keys %$volid_hash) {
5816 next if $volid =~ m/vm-$vmid-state-/;
c449137a 5817 next if $referenced->{$volid};
5996a936
DM
5818 my $path = $volid_hash->{$volid}->{path};
5819 next if !$path; # just to be sure
c449137a 5820 next if $referencedpath->{$path};
91bd6c90 5821 $changes = 1;
53b81297
TL
5822 my $key = PVE::QemuConfig->add_unused_volume($conf, $volid);
5823 print "$prefix add unreferenced volume '$volid' as '$key' to config.\n";
c449137a 5824 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
5825 }
5826
5827 return $changes;
5828}
5829
5830sub rescan {
9224dcee 5831 my ($vmid, $nolock, $dryrun) = @_;
91bd6c90 5832
20519efc 5833 my $cfg = PVE::Storage::config();
91bd6c90 5834
b9a1a3ab
TL
5835 # FIXME: Remove once our RBD plugin can handle CT and VM on a single storage
5836 # see: https://pve.proxmox.com/pipermail/pve-devel/2018-July/032900.html
4771526a
AA
5837 foreach my $stor (keys %{$cfg->{ids}}) {
5838 delete($cfg->{ids}->{$stor}) if ! $cfg->{ids}->{$stor}->{content}->{images};
5839 }
5840
53b81297 5841 print "rescan volumes...\n";
91bd6c90
DM
5842 my $volid_hash = scan_volids($cfg, $vmid);
5843
5844 my $updatefn = sub {
5845 my ($vmid) = @_;
5846
ffda963f 5847 my $conf = PVE::QemuConfig->load_config($vmid);
be190583 5848
ffda963f 5849 PVE::QemuConfig->check_lock($conf);
91bd6c90 5850
03da3f0d
DM
5851 my $vm_volids = {};
5852 foreach my $volid (keys %$volid_hash) {
5853 my $info = $volid_hash->{$volid};
5854 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
5855 }
5856
5857 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 5858
9224dcee 5859 PVE::QemuConfig->write_config($vmid, $conf) if $changes && !$dryrun;
91bd6c90
DM
5860 };
5861
5862 if (defined($vmid)) {
5863 if ($nolock) {
5864 &$updatefn($vmid);
5865 } else {
ffda963f 5866 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
5867 }
5868 } else {
5869 my $vmlist = config_list();
5870 foreach my $vmid (keys %$vmlist) {
5871 if ($nolock) {
5872 &$updatefn($vmid);
5873 } else {
ffda963f 5874 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
be190583 5875 }
91bd6c90
DM
5876 }
5877 }
5878}
5879
5880sub restore_vma_archive {
5881 my ($archive, $vmid, $user, $opts, $comp) = @_;
5882
91bd6c90
DM
5883 my $readfrom = $archive;
5884
7c536e11
WB
5885 my $cfg = PVE::Storage::config();
5886 my $commands = [];
5887 my $bwlimit = $opts->{bwlimit};
5888
5889 my $dbg_cmdstring = '';
5890 my $add_pipe = sub {
5891 my ($cmd) = @_;
5892 push @$commands, $cmd;
5893 $dbg_cmdstring .= ' | ' if length($dbg_cmdstring);
5894 $dbg_cmdstring .= PVE::Tools::cmd2string($cmd);
91bd6c90 5895 $readfrom = '-';
7c536e11
WB
5896 };
5897
5898 my $input = undef;
5899 if ($archive eq '-') {
5900 $input = '<&STDIN';
5901 } else {
5902 # If we use a backup from a PVE defined storage we also consider that
5903 # storage's rate limit:
5904 my (undef, $volid) = PVE::Storage::path_to_volume_id($cfg, $archive);
5905 if (defined($volid)) {
5906 my ($sid, undef) = PVE::Storage::parse_volume_id($volid);
5907 my $readlimit = PVE::Storage::get_bandwidth_limit('restore', [$sid], $bwlimit);
5908 if ($readlimit) {
5909 print STDERR "applying read rate limit: $readlimit\n";
9444c6e4 5910 my $cstream = ['cstream', '-t', $readlimit*1024, '--', $readfrom];
7c536e11
WB
5911 $add_pipe->($cstream);
5912 }
5913 }
5914 }
5915
5916 if ($comp) {
5917 my $cmd;
91bd6c90 5918 if ($comp eq 'gzip') {
7c536e11 5919 $cmd = ['zcat', $readfrom];
91bd6c90 5920 } elsif ($comp eq 'lzop') {
7c536e11 5921 $cmd = ['lzop', '-d', '-c', $readfrom];
91bd6c90
DM
5922 } else {
5923 die "unknown compression method '$comp'\n";
5924 }
7c536e11 5925 $add_pipe->($cmd);
91bd6c90
DM
5926 }
5927
5928 my $tmpdir = "/var/tmp/vzdumptmp$$";
5929 rmtree $tmpdir;
5930
5931 # disable interrupts (always do cleanups)
5b97ef24
TL
5932 local $SIG{INT} =
5933 local $SIG{TERM} =
5934 local $SIG{QUIT} =
5935 local $SIG{HUP} = sub { warn "got interrupt - ignored\n"; };
91bd6c90
DM
5936
5937 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5938 POSIX::mkfifo($mapfifo, 0600);
5939 my $fifofh;
5940
5941 my $openfifo = sub {
5942 open($fifofh, '>', $mapfifo) || die $!;
5943 };
5944
7c536e11 5945 $add_pipe->(['vma', 'extract', '-v', '-r', $mapfifo, $readfrom, $tmpdir]);
91bd6c90
DM
5946
5947 my $oldtimeout;
5948 my $timeout = 5;
5949
5950 my $devinfo = {};
5951
5952 my $rpcenv = PVE::RPCEnvironment::get();
5953
ffda963f 5954 my $conffile = PVE::QemuConfig->config_file($vmid);
91bd6c90
DM
5955 my $tmpfn = "$conffile.$$.tmp";
5956
ed221350 5957 # Note: $oldconf is undef if VM does not exists
ffda963f
FG
5958 my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
5959 my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
ed221350 5960
7c536e11
WB
5961 my %storage_limits;
5962
91bd6c90
DM
5963 my $print_devmap = sub {
5964 my $virtdev_hash = {};
5965
5966 my $cfgfn = "$tmpdir/qemu-server.conf";
5967
5968 # we can read the config - that is already extracted
5969 my $fh = IO::File->new($cfgfn, "r") ||
5970 "unable to read qemu-server.conf - $!\n";
5971
6738ab9c 5972 my $fwcfgfn = "$tmpdir/qemu-server.fw";
3457d090
WL
5973 if (-f $fwcfgfn) {
5974 my $pve_firewall_dir = '/etc/pve/firewall';
5975 mkdir $pve_firewall_dir; # make sure the dir exists
5976 PVE::Tools::file_copy($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5977 }
6738ab9c 5978
91bd6c90
DM
5979 while (defined(my $line = <$fh>)) {
5980 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5981 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5982 die "archive does not contain data for drive '$virtdev'\n"
5983 if !$devinfo->{$devname};
5984 if (defined($opts->{storage})) {
5985 $storeid = $opts->{storage} || 'local';
5986 } elsif (!$storeid) {
5987 $storeid = 'local';
5988 }
5989 $format = 'raw' if !$format;
5990 $devinfo->{$devname}->{devname} = $devname;
5991 $devinfo->{$devname}->{virtdev} = $virtdev;
5992 $devinfo->{$devname}->{format} = $format;
5993 $devinfo->{$devname}->{storeid} = $storeid;
5994
be190583 5995 # check permission on storage
91bd6c90
DM
5996 my $pool = $opts->{pool}; # todo: do we need that?
5997 if ($user ne 'root@pam') {
5998 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5999 }
6000
7c536e11
WB
6001 $storage_limits{$storeid} = $bwlimit;
6002
91bd6c90
DM
6003 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
6004 }
6005 }
6006
7c536e11
WB
6007 foreach my $key (keys %storage_limits) {
6008 my $limit = PVE::Storage::get_bandwidth_limit('restore', [$key], $bwlimit);
6009 next if !$limit;
6010 print STDERR "rate limit for storage $key: $limit KiB/s\n";
6011 $storage_limits{$key} = $limit * 1024;
6012 }
6013
91bd6c90 6014 foreach my $devname (keys %$devinfo) {
be190583
DM
6015 die "found no device mapping information for device '$devname'\n"
6016 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
6017 }
6018
ed221350 6019 # create empty/temp config
be190583 6020 if ($oldconf) {
ed221350
DM
6021 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
6022 foreach_drive($oldconf, sub {
6023 my ($ds, $drive) = @_;
6024
6025 return if drive_is_cdrom($drive);
6026
6027 my $volid = $drive->{file};
6028
6029 return if !$volid || $volid =~ m|^/|;
6030
6031 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
6032 return if !$path || !$owner || ($owner != $vmid);
6033
6034 # Note: only delete disk we want to restore
6035 # other volumes will become unused
6036 if ($virtdev_hash->{$ds}) {
6b72854b
FG
6037 eval { PVE::Storage::vdisk_free($cfg, $volid); };
6038 if (my $err = $@) {
6039 warn $err;
6040 }
ed221350
DM
6041 }
6042 });
381b8fae
DC
6043
6044 # delete vmstate files
6045 # since after the restore we have no snapshots anymore
6046 foreach my $snapname (keys %{$oldconf->{snapshots}}) {
6047 my $snap = $oldconf->{snapshots}->{$snapname};
6048 if ($snap->{vmstate}) {
6049 eval { PVE::Storage::vdisk_free($cfg, $snap->{vmstate}); };
6050 if (my $err = $@) {
6051 warn $err;
6052 }
6053 }
6054 }
ed221350
DM
6055 }
6056
6057 my $map = {};
91bd6c90
DM
6058 foreach my $virtdev (sort keys %$virtdev_hash) {
6059 my $d = $virtdev_hash->{$virtdev};
6060 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
7c536e11
WB
6061 my $storeid = $d->{storeid};
6062 my $scfg = PVE::Storage::storage_config($cfg, $storeid);
6063
6064 my $map_opts = '';
6065 if (my $limit = $storage_limits{$storeid}) {
6066 $map_opts .= "throttling.bps=$limit:throttling.group=$storeid:";
6067 }
8fd57431
DM
6068
6069 # test if requested format is supported
7c536e11 6070 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $storeid);
8fd57431
DM
6071 my $supported = grep { $_ eq $d->{format} } @$validFormats;
6072 $d->{format} = $defFormat if !$supported;
6073
7c536e11 6074 my $volid = PVE::Storage::vdisk_alloc($cfg, $storeid, $vmid,
91bd6c90
DM
6075 $d->{format}, undef, $alloc_size);
6076 print STDERR "new volume ID is '$volid'\n";
6077 $d->{volid} = $volid;
6078 my $path = PVE::Storage::path($cfg, $volid);
6079
5f96f4df
WL
6080 PVE::Storage::activate_volumes($cfg,[$volid]);
6081
91bd6c90 6082 my $write_zeros = 1;
88240a83 6083 if (PVE::Storage::volume_has_feature($cfg, 'sparseinit', $volid)) {
91bd6c90
DM
6084 $write_zeros = 0;
6085 }
6086
7c536e11 6087 print $fifofh "${map_opts}format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
91bd6c90
DM
6088
6089 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
6090 $map->{$virtdev} = $volid;
6091 }
6092
6093 $fh->seek(0, 0) || die "seek failed - $!\n";
6094
6095 my $outfd = new IO::File ($tmpfn, "w") ||
6096 die "unable to write config for VM $vmid\n";
6097
6098 my $cookie = { netcount => 0 };
6099 while (defined(my $line = <$fh>)) {
be190583 6100 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
6101 }
6102
6103 $fh->close();
6104 $outfd->close();
6105 };
6106
6107 eval {
6108 # enable interrupts
6cb0144a
EK
6109 local $SIG{INT} =
6110 local $SIG{TERM} =
6111 local $SIG{QUIT} =
6112 local $SIG{HUP} =
6113 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
91bd6c90
DM
6114 local $SIG{ALRM} = sub { die "got timeout\n"; };
6115
6116 $oldtimeout = alarm($timeout);
6117
6118 my $parser = sub {
6119 my $line = shift;
6120
6121 print "$line\n";
6122
6123 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
6124 my ($dev_id, $size, $devname) = ($1, $2, $3);
6125 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
6126 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 6127 # we correctly received the vma config, so we can disable
3cf90d7a
DM
6128 # the timeout now for disk allocation (set to 10 minutes, so
6129 # that we always timeout if something goes wrong)
6130 alarm(600);
91bd6c90
DM
6131 &$print_devmap();
6132 print $fifofh "done\n";
6133 my $tmp = $oldtimeout || 0;
6134 $oldtimeout = undef;
6135 alarm($tmp);
6136 close($fifofh);
6137 }
6138 };
be190583 6139
7c536e11
WB
6140 print "restore vma archive: $dbg_cmdstring\n";
6141 run_command($commands, input => $input, outfunc => $parser, afterfork => $openfifo);
91bd6c90
DM
6142 };
6143 my $err = $@;
6144
6145 alarm($oldtimeout) if $oldtimeout;
6146
5f96f4df
WL
6147 my $vollist = [];
6148 foreach my $devname (keys %$devinfo) {
6149 my $volid = $devinfo->{$devname}->{volid};
6150 push @$vollist, $volid if $volid;
6151 }
6152
5f96f4df
WL
6153 PVE::Storage::deactivate_volumes($cfg, $vollist);
6154
91bd6c90
DM
6155 unlink $mapfifo;
6156
6157 if ($err) {
6158 rmtree $tmpdir;
6159 unlink $tmpfn;
6160
91bd6c90
DM
6161 foreach my $devname (keys %$devinfo) {
6162 my $volid = $devinfo->{$devname}->{volid};
6163 next if !$volid;
6164 eval {
6165 if ($volid =~ m|^/|) {
6166 unlink $volid || die 'unlink failed\n';
6167 } else {
6168 PVE::Storage::vdisk_free($cfg, $volid);
6169 }
6170 print STDERR "temporary volume '$volid' sucessfuly removed\n";
6171 };
6172 print STDERR "unable to cleanup '$volid' - $@" if $@;
6173 }
6174 die $err;
6175 }
6176
6177 rmtree $tmpdir;
ed221350
DM
6178
6179 rename($tmpfn, $conffile) ||
91bd6c90
DM
6180 die "unable to commit configuration file '$conffile'\n";
6181
ed221350
DM
6182 PVE::Cluster::cfs_update(); # make sure we read new file
6183
91bd6c90
DM
6184 eval { rescan($vmid, 1); };
6185 warn $@ if $@;
6186}
6187
6188sub restore_tar_archive {
6189 my ($archive, $vmid, $user, $opts) = @_;
6190
9c502e26 6191 if ($archive ne '-') {
ed221350 6192 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
6193 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
6194 if $firstfile ne 'qemu-server.conf';
6195 }
3e16d5fc 6196
20519efc 6197 my $storecfg = PVE::Storage::config();
ebb55558 6198
ed221350 6199 # destroy existing data - keep empty config
ffda963f 6200 my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
ebb55558 6201 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 6202
3e16d5fc
DM
6203 my $tocmd = "/usr/lib/qemu-server/qmextract";
6204
2415a446 6205 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 6206 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
6207 $tocmd .= ' --prealloc' if $opts->{prealloc};
6208 $tocmd .= ' --info' if $opts->{info};
6209
a0d1b1a2 6210 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 6211 # so we pipe to zcat
2415a446
DM
6212 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
6213 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
6214
6215 my $tmpdir = "/var/tmp/vzdumptmp$$";
6216 mkpath $tmpdir;
6217
6218 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
6219 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 6220 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 6221
ffda963f 6222 my $conffile = PVE::QemuConfig->config_file($vmid);
3e16d5fc
DM
6223 my $tmpfn = "$conffile.$$.tmp";
6224
6225 # disable interrupts (always do cleanups)
6cb0144a
EK
6226 local $SIG{INT} =
6227 local $SIG{TERM} =
6228 local $SIG{QUIT} =
6229 local $SIG{HUP} = sub { print STDERR "got interrupt - ignored\n"; };
3e16d5fc 6230
afdb31d5 6231 eval {
3e16d5fc 6232 # enable interrupts
6cb0144a
EK
6233 local $SIG{INT} =
6234 local $SIG{TERM} =
6235 local $SIG{QUIT} =
6236 local $SIG{HUP} =
6237 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
3e16d5fc 6238
9c502e26
DM
6239 if ($archive eq '-') {
6240 print "extracting archive from STDIN\n";
6241 run_command($cmd, input => "<&STDIN");
6242 } else {
6243 print "extracting archive '$archive'\n";
6244 run_command($cmd);
6245 }
3e16d5fc
DM
6246
6247 return if $opts->{info};
6248
6249 # read new mapping
6250 my $map = {};
6251 my $statfile = "$tmpdir/qmrestore.stat";
6252 if (my $fd = IO::File->new($statfile, "r")) {
6253 while (defined (my $line = <$fd>)) {
6254 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
6255 $map->{$1} = $2 if $1;
6256 } else {
6257 print STDERR "unable to parse line in statfile - $line\n";
6258 }
6259 }
6260 $fd->close();
6261 }
6262
6263 my $confsrc = "$tmpdir/qemu-server.conf";
6264
6265 my $srcfd = new IO::File($confsrc, "r") ||
6266 die "unable to open file '$confsrc'\n";
6267
6268 my $outfd = new IO::File ($tmpfn, "w") ||
6269 die "unable to write config for VM $vmid\n";
6270
91bd6c90 6271 my $cookie = { netcount => 0 };
3e16d5fc 6272 while (defined (my $line = <$srcfd>)) {
be190583 6273 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
6274 }
6275
6276 $srcfd->close();
6277 $outfd->close();
6278 };
6279 my $err = $@;
6280
afdb31d5 6281 if ($err) {
3e16d5fc
DM
6282
6283 unlink $tmpfn;
6284
ed221350 6285 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 6286
3e16d5fc 6287 die $err;
afdb31d5 6288 }
3e16d5fc
DM
6289
6290 rmtree $tmpdir;
6291
6292 rename $tmpfn, $conffile ||
6293 die "unable to commit configuration file '$conffile'\n";
91bd6c90 6294
ed221350
DM
6295 PVE::Cluster::cfs_update(); # make sure we read new file
6296
91bd6c90
DM
6297 eval { rescan($vmid, 1); };
6298 warn $@ if $@;
3e16d5fc
DM
6299};
6300
65a5ce88 6301sub foreach_storage_used_by_vm {
18bfb361
DM
6302 my ($conf, $func) = @_;
6303
6304 my $sidhash = {};
6305
8ddbcf8b
FG
6306 foreach_drive($conf, sub {
6307 my ($ds, $drive) = @_;
6308 return if drive_is_cdrom($drive);
18bfb361
DM
6309
6310 my $volid = $drive->{file};
6311
6312 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 6313 $sidhash->{$sid} = $sid if $sid;
8ddbcf8b 6314 });
18bfb361
DM
6315
6316 foreach my $sid (sort keys %$sidhash) {
6317 &$func($sid);
6318 }
6319}
6320
e5eaa028
WL
6321sub do_snapshots_with_qemu {
6322 my ($storecfg, $volid) = @_;
6323
6324 my $storage_name = PVE::Storage::parse_volume_id($volid);
6325
116da784
WL
6326 if ($qemu_snap_storage->{$storecfg->{ids}->{$storage_name}->{type}}
6327 && !$storecfg->{ids}->{$storage_name}->{krbd}){
e5eaa028
WL
6328 return 1;
6329 }
6330
6331 if ($volid =~ m/\.(qcow2|qed)$/){
6332 return 1;
6333 }
6334
6335 return undef;
6336}
6337
4dcc780c 6338sub qga_check_running {
a4938c72 6339 my ($vmid, $nowarn) = @_;
4dcc780c
WL
6340
6341 eval { vm_mon_cmd($vmid, "guest-ping", timeout => 3); };
6342 if ($@) {
a4938c72 6343 warn "Qemu Guest Agent is not running - $@" if !$nowarn;
4dcc780c
WL
6344 return 0;
6345 }
6346 return 1;
6347}
6348
04a69bb4
AD
6349sub template_create {
6350 my ($vmid, $conf, $disk) = @_;
6351
04a69bb4 6352 my $storecfg = PVE::Storage::config();
04a69bb4 6353
9cd07842
DM
6354 foreach_drive($conf, sub {
6355 my ($ds, $drive) = @_;
6356
6357 return if drive_is_cdrom($drive);
6358 return if $disk && $ds ne $disk;
6359
6360 my $volid = $drive->{file};
bbd56097 6361 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 6362
04a69bb4
AD
6363 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
6364 $drive->{file} = $voliddst;
152fe752 6365 $conf->{$ds} = print_drive($vmid, $drive);
ffda963f 6366 PVE::QemuConfig->write_config($vmid, $conf);
04a69bb4 6367 });
04a69bb4
AD
6368}
6369
5133de42 6370sub qemu_img_convert {
988e2714 6371 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5133de42
AD
6372
6373 my $storecfg = PVE::Storage::config();
6374 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
6375 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
6376
6377 if ($src_storeid && $dst_storeid) {
6bb91c17
DM
6378
6379 PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
6380
5133de42
AD
6381 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
6382 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
6383
6384 my $src_format = qemu_img_format($src_scfg, $src_volname);
6385 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
6386
6387 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
6388 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
6389
6390 my $cmd = [];
eed24303 6391 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
29004a20 6392 push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
d4940091
FG
6393 push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
6394 push @$cmd, '-T', 'none' if $src_scfg->{type} eq 'zfspool';
988e2714
WB
6395 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
6396 if ($is_zero_initialized) {
6397 push @$cmd, "zeroinit:$dst_path";
6398 } else {
6399 push @$cmd, $dst_path;
6400 }
5133de42
AD
6401
6402 my $parser = sub {
6403 my $line = shift;
6404 if($line =~ m/\((\S+)\/100\%\)/){
6405 my $percent = $1;
6406 my $transferred = int($size * $percent / 100);
6407 my $remaining = $size - $transferred;
6408
6409 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6410 }
6411
6412 };
6413
6414 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
6415 my $err = $@;
6416 die "copy failed: $err" if $err;
6417 }
6418}
6419
6420sub qemu_img_format {
6421 my ($scfg, $volname) = @_;
6422
9c52f5ed 6423 if ($scfg->{path} && $volname =~ m/\.($QEMU_FORMAT_RE)$/) {
5133de42 6424 return $1;
be190583 6425 } else {
5133de42 6426 return "raw";
5133de42
AD
6427 }
6428}
6429
cfad42af 6430sub qemu_drive_mirror {
5619e74a 6431 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
cfad42af 6432
5a345967
AD
6433 $jobs = {} if !$jobs;
6434
6435 my $qemu_target;
6436 my $format;
35e4ab04 6437 $jobs->{"drive-$drive"} = {};
152fe752 6438
1e5143de 6439 if ($dst_volid =~ /^nbd:/) {
87955688 6440 $qemu_target = $dst_volid;
5a345967 6441 $format = "nbd";
5a345967 6442 } else {
5a345967
AD
6443 my $storecfg = PVE::Storage::config();
6444 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid);
6445
6446 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
cfad42af 6447
5a345967 6448 $format = qemu_img_format($dst_scfg, $dst_volname);
21ccdb50 6449
5a345967 6450 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
21ccdb50 6451
5a345967
AD
6452 $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
6453 }
988e2714
WB
6454
6455 my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
88383920
DM
6456 $opts->{format} = $format if $format;
6457
5a345967 6458 print "drive mirror is starting for drive-$drive\n";
21ccdb50 6459
5a345967 6460 eval { vm_mon_cmd($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
35e4ab04 6461
5a345967
AD
6462 if (my $err = $@) {
6463 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
6464 die "mirroring error: $err";
6465 }
6466
5619e74a 6467 qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
5a345967
AD
6468}
6469
6470sub qemu_drive_mirror_monitor {
5619e74a 6471 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
2e953867 6472
08ac653f 6473 eval {
5a345967
AD
6474 my $err_complete = 0;
6475
08ac653f 6476 while (1) {
5a345967
AD
6477 die "storage migration timed out\n" if $err_complete > 300;
6478
08ac653f 6479 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
08ac653f 6480
5a345967
AD
6481 my $running_mirror_jobs = {};
6482 foreach my $stat (@$stats) {
6483 next if $stat->{type} ne 'mirror';
6484 $running_mirror_jobs->{$stat->{device}} = $stat;
6485 }
08ac653f 6486
5a345967 6487 my $readycounter = 0;
67fb9de6 6488
5a345967
AD
6489 foreach my $job (keys %$jobs) {
6490
6491 if(defined($jobs->{$job}->{complete}) && !defined($running_mirror_jobs->{$job})) {
6492 print "$job : finished\n";
6493 delete $jobs->{$job};
6494 next;
6495 }
6496
bd2d5fe6 6497 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
f34ebd52 6498
5a345967
AD
6499 my $busy = $running_mirror_jobs->{$job}->{busy};
6500 my $ready = $running_mirror_jobs->{$job}->{ready};
6501 if (my $total = $running_mirror_jobs->{$job}->{len}) {
6502 my $transferred = $running_mirror_jobs->{$job}->{offset} || 0;
6503 my $remaining = $total - $transferred;
6504 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
08ac653f 6505
5a345967
AD
6506 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6507 }
f34ebd52 6508
d1782eba 6509 $readycounter++ if $running_mirror_jobs->{$job}->{ready};
5a345967 6510 }
b467f79a 6511
5a345967
AD
6512 last if scalar(keys %$jobs) == 0;
6513
6514 if ($readycounter == scalar(keys %$jobs)) {
6515 print "all mirroring jobs are ready \n";
6516 last if $skipcomplete; #do the complete later
6517
6518 if ($vmiddst && $vmiddst != $vmid) {
1a988fd2
DC
6519 my $agent_running = $qga && qga_check_running($vmid);
6520 if ($agent_running) {
5619e74a
AD
6521 print "freeze filesystem\n";
6522 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-freeze"); };
6523 } else {
6524 print "suspend vm\n";
6525 eval { PVE::QemuServer::vm_suspend($vmid, 1); };
6526 }
6527
5a345967
AD
6528 # if we clone a disk for a new target vm, we don't switch the disk
6529 PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs);
5619e74a 6530
1a988fd2 6531 if ($agent_running) {
5619e74a
AD
6532 print "unfreeze filesystem\n";
6533 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-thaw"); };
6534 } else {
6535 print "resume vm\n";
6536 eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
6537 }
6538
2e953867 6539 last;
5a345967
AD
6540 } else {
6541
6542 foreach my $job (keys %$jobs) {
6543 # try to switch the disk if source and destination are on the same guest
bd2d5fe6 6544 print "$job: Completing block job...\n";
5a345967
AD
6545
6546 eval { vm_mon_cmd($vmid, "block-job-complete", device => $job) };
6547 if ($@ =~ m/cannot be completed/) {
bd2d5fe6 6548 print "$job: Block job cannot be completed, try again.\n";
5a345967
AD
6549 $err_complete++;
6550 }else {
bd2d5fe6 6551 print "$job: Completed successfully.\n";
5a345967
AD
6552 $jobs->{$job}->{complete} = 1;
6553 }
6554 }
2e953867 6555 }
08ac653f 6556 }
08ac653f 6557 sleep 1;
cfad42af 6558 }
08ac653f 6559 };
88383920 6560 my $err = $@;
08ac653f 6561
88383920 6562 if ($err) {
5a345967 6563 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
88383920
DM
6564 die "mirroring error: $err";
6565 }
6566
5a345967
AD
6567}
6568
6569sub qemu_blockjobs_cancel {
6570 my ($vmid, $jobs) = @_;
6571
6572 foreach my $job (keys %$jobs) {
bd2d5fe6 6573 print "$job: Cancelling block job\n";
5a345967
AD
6574 eval { vm_mon_cmd($vmid, "block-job-cancel", device => $job); };
6575 $jobs->{$job}->{cancel} = 1;
6576 }
6577
6578 while (1) {
6579 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
6580
6581 my $running_jobs = {};
6582 foreach my $stat (@$stats) {
6583 $running_jobs->{$stat->{device}} = $stat;
6584 }
6585
6586 foreach my $job (keys %$jobs) {
6587
bd2d5fe6
WB
6588 if (defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
6589 print "$job: Done.\n";
5a345967
AD
6590 delete $jobs->{$job};
6591 }
6592 }
6593
6594 last if scalar(keys %$jobs) == 0;
6595
6596 sleep 1;
cfad42af
AD
6597 }
6598}
6599
152fe752 6600sub clone_disk {
be190583 6601 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5619e74a 6602 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
152fe752
DM
6603
6604 my $newvolid;
6605
6606 if (!$full) {
6607 print "create linked clone of drive $drivename ($drive->{file})\n";
258e646c 6608 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
152fe752
DM
6609 push @$newvollist, $newvolid;
6610 } else {
5a345967 6611
152fe752
DM
6612 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
6613 $storeid = $storage if $storage;
6614
44549149 6615 my $dst_format = resolve_dst_disk_format($storecfg, $storeid, $volname, $format);
152fe752
DM
6616 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
6617
6618 print "create full clone of drive $drivename ($drive->{file})\n";
931432bd
WB
6619 my $name = undef;
6620 if (drive_is_cloudinit($drive)) {
6621 $name = "vm-$newvmid-cloudinit";
6622 # cloudinit only supports raw and qcow2 atm:
6623 if ($dst_format eq 'qcow2') {
6624 $name .= '.qcow2';
6625 } elsif ($dst_format ne 'raw') {
6626 die "clone: unhandled format for cloudinit image\n";
6627 }
6628 }
6629 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024));
152fe752
DM
6630 push @$newvollist, $newvolid;
6631
3999f370 6632 PVE::Storage::activate_volumes($storecfg, [$newvolid]);
1dbd6d30 6633
988e2714 6634 my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
152fe752 6635 if (!$running || $snapname) {
988e2714 6636 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit);
152fe752 6637 } else {
2e541679
AD
6638
6639 my $kvmver = get_running_qemu_version ($vmid);
6640 if (!qemu_machine_feature_enabled (undef, $kvmver, 2, 7)) {
961af8a3
WB
6641 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6642 if $drive->{iothread};
2e541679 6643 }
2af848a2 6644
5619e74a 6645 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
be190583 6646 }
152fe752
DM
6647 }
6648
6649 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
6650
6651 my $disk = $drive;
6652 $disk->{format} = undef;
6653 $disk->{file} = $newvolid;
6654 $disk->{size} = $size;
6655
6656 return $disk;
6657}
6658
ff556cf2
DM
6659# this only works if VM is running
6660sub get_current_qemu_machine {
6661 my ($vmid) = @_;
6662
6663 my $cmd = { execute => 'query-machines', arguments => {} };
8e90138a 6664 my $res = vm_qmp_command($vmid, $cmd);
ff556cf2
DM
6665
6666 my ($current, $default);
6667 foreach my $e (@$res) {
6668 $default = $e->{name} if $e->{'is-default'};
6669 $current = $e->{name} if $e->{'is-current'};
6670 }
6671
6672 # fallback to the default machine if current is not supported by qemu
6673 return $current || $default || 'pc';
6674}
6675
98cfd8b6
AD
6676sub get_running_qemu_version {
6677 my ($vmid) = @_;
6678 my $cmd = { execute => 'query-version', arguments => {} };
6679 my $res = vm_qmp_command($vmid, $cmd);
6680 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6681}
6682
23f73120
AD
6683sub qemu_machine_feature_enabled {
6684 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6685
6686 my $current_major;
6687 my $current_minor;
6688
d731ecbe 6689 if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
23f73120
AD
6690
6691 $current_major = $3;
6692 $current_minor = $4;
6693
6694 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6695
6696 $current_major = $1;
6697 $current_minor = $2;
6698 }
6699
dd84e5ec
WB
6700 return 1 if $current_major > $version_major ||
6701 ($current_major == $version_major &&
6702 $current_minor >= $version_minor);
23f73120
AD
6703}
6704
42dbd2ee
AD
6705sub qemu_machine_pxe {
6706 my ($vmid, $conf, $machine) = @_;
6707
6708 $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine;
6709
3807f3e4
DC
6710 if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
6711 $machine .= '.pxe';
42dbd2ee
AD
6712 }
6713
d1363934 6714 return $machine;
42dbd2ee
AD
6715}
6716
249c4a6c
AD
6717sub qemu_use_old_bios_files {
6718 my ($machine_type) = @_;
6719
6720 return if !$machine_type;
6721
6722 my $use_old_bios_files = undef;
6723
6724 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6725 $machine_type = $1;
6726 $use_old_bios_files = 1;
6727 } else {
74cc511f 6728 my $kvmver = kvm_user_version();
249c4a6c
AD
6729 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6730 # load new efi bios files on migration. So this hack is required to allow
6731 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6732 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
74cc511f 6733 $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
249c4a6c
AD
6734 }
6735
6736 return ($use_old_bios_files, $machine_type);
6737}
6738
96ed3574
WB
6739sub create_efidisk($$$$$) {
6740 my ($storecfg, $storeid, $vmid, $fmt, $arch) = @_;
3e1f1122 6741
96ed3574
WB
6742 my (undef, $ovmf_vars) = get_ovmf_files($arch);
6743 die "EFI vars default image not found\n" if ! -f $ovmf_vars;
3e1f1122 6744
96ed3574 6745 my $vars_size = PVE::Tools::convert_size(-s $ovmf_vars, 'b' => 'kb');
3e1f1122
TL
6746 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6747 PVE::Storage::activate_volumes($storecfg, [$volid]);
6748
6749 my $path = PVE::Storage::path($storecfg, $volid);
6750 eval {
96ed3574 6751 run_command(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $ovmf_vars, $path]);
3e1f1122
TL
6752 };
6753 die "Copying EFI vars image failed: $@" if $@;
6754
6755 return ($volid, $vars_size);
6756}
6757
22de899a
AD
6758sub vm_iothreads_list {
6759 my ($vmid) = @_;
6760
6761 my $res = vm_mon_cmd($vmid, 'query-iothreads');
6762
6763 my $iothreads = {};
6764 foreach my $iothread (@$res) {
6765 $iothreads->{ $iothread->{id} } = $iothread->{"thread-id"};
6766 }
6767
6768 return $iothreads;
6769}
6770
ee034f5c
AD
6771sub scsihw_infos {
6772 my ($conf, $drive) = @_;
6773
6774 my $maxdev = 0;
6775
7fe1b688 6776 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
ee034f5c 6777 $maxdev = 7;
a1511b3c 6778 } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
ee034f5c
AD
6779 $maxdev = 1;
6780 } else {
6781 $maxdev = 256;
6782 }
6783
6784 my $controller = int($drive->{index} / $maxdev);
a1511b3c 6785 my $controller_prefix = ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') ? "virtioscsi" : "scsihw";
ee034f5c
AD
6786
6787 return ($maxdev, $controller, $controller_prefix);
6788}
a1511b3c 6789
075e8249
PA
6790sub add_hyperv_enlightenments {
6791 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
4317f69f 6792
4317f69f
AD
6793 return if $winversion < 6;
6794 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6795
5aba3953
AD
6796 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6797
4317f69f
AD
6798 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
6799 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6800 push @$cpuFlags , 'hv_vapic';
6801 push @$cpuFlags , 'hv_time';
6802 } else {
6803 push @$cpuFlags , 'hv_spinlocks=0xffff';
6804 }
6805
6806 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
6807 push @$cpuFlags , 'hv_reset';
6808 push @$cpuFlags , 'hv_vpindex';
6809 push @$cpuFlags , 'hv_runtime';
6810 }
6811
6812 if ($winversion >= 7) {
6813 push @$cpuFlags , 'hv_relaxed';
ebb346d6 6814
df648a6a 6815 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 12)) {
ebb346d6
AD
6816 push @$cpuFlags , 'hv_synic';
6817 push @$cpuFlags , 'hv_stimer';
6818 }
4317f69f
AD
6819 }
6820}
6821
6822sub windows_version {
6823 my ($ostype) = @_;
6824
6825 return 0 if !$ostype;
6826
6827 my $winversion = 0;
6828
6829 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6830 $winversion = 5;
6831 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6832 $winversion = 6;
6833 } elsif ($ostype =~ m/^win(\d+)$/) {
6834 $winversion = $1;
6835 }
6836
6837 return $winversion;
6838}
6839
44549149
EK
6840sub resolve_dst_disk_format {
6841 my ($storecfg, $storeid, $src_volname, $format) = @_;
6842 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
6843
6844 if (!$format) {
6845 # if no target format is specified, use the source disk format as hint
6846 if ($src_volname) {
6847 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
6848 $format = qemu_img_format($scfg, $src_volname);
6849 } else {
6850 return $defFormat;
6851 }
6852 }
6853
6854 # test if requested format is supported - else use default
6855 my $supported = grep { $_ eq $format } @$validFormats;
6856 $format = $defFormat if !$supported;
6857 return $format;
6858}
6859
ae2fcb3b
EK
6860sub resolve_first_disk {
6861 my $conf = shift;
6862 my @disks = PVE::QemuServer::valid_drive_names();
6863 my $firstdisk;
6864 foreach my $ds (reverse @disks) {
6865 next if !$conf->{$ds};
6866 my $disk = PVE::QemuServer::parse_drive($ds, $conf->{$ds});
6867 next if PVE::QemuServer::drive_is_cdrom($disk);
6868 $firstdisk = $ds;
6869 }
6870 return $firstdisk;
6871}
6872
6ee499ff 6873sub generate_uuid {
ae2fcb3b
EK
6874 my ($uuid, $uuid_str);
6875 UUID::generate($uuid);
6876 UUID::unparse($uuid, $uuid_str);
6ee499ff
DC
6877 return $uuid_str;
6878}
6879
6880sub generate_smbios1_uuid {
6881 return "uuid=".generate_uuid();
ae2fcb3b
EK
6882}
6883
9c152e87
TL
6884sub nbd_stop {
6885 my ($vmid) = @_;
6886
6887 vm_mon_cmd($vmid, 'nbd-server-stop');
6888}
6889
65e866e5
DM
6890# bash completion helper
6891
6892sub complete_backup_archives {
6893 my ($cmdname, $pname, $cvalue) = @_;
6894
6895 my $cfg = PVE::Storage::config();
6896
6897 my $storeid;
6898
6899 if ($cvalue =~ m/^([^:]+):/) {
6900 $storeid = $1;
6901 }
6902
6903 my $data = PVE::Storage::template_list($cfg, $storeid, 'backup');
6904
6905 my $res = [];
6906 foreach my $id (keys %$data) {
6907 foreach my $item (@{$data->{$id}}) {
6908 next if $item->{format} !~ m/^vma\.(gz|lzo)$/;
6909 push @$res, $item->{volid} if defined($item->{volid});
6910 }
6911 }
6912
6913 return $res;
6914}
6915
6916my $complete_vmid_full = sub {
6917 my ($running) = @_;
6918
6919 my $idlist = vmstatus();
6920
6921 my $res = [];
6922
6923 foreach my $id (keys %$idlist) {
6924 my $d = $idlist->{$id};
6925 if (defined($running)) {
6926 next if $d->{template};
6927 next if $running && $d->{status} ne 'running';
6928 next if !$running && $d->{status} eq 'running';
6929 }
6930 push @$res, $id;
6931
6932 }
6933 return $res;
6934};
6935
6936sub complete_vmid {
6937 return &$complete_vmid_full();
6938}
6939
6940sub complete_vmid_stopped {
6941 return &$complete_vmid_full(0);
6942}
6943
6944sub complete_vmid_running {
6945 return &$complete_vmid_full(1);
6946}
6947
335af808
DM
6948sub complete_storage {
6949
6950 my $cfg = PVE::Storage::config();
6951 my $ids = $cfg->{ids};
6952
6953 my $res = [];
6954 foreach my $sid (keys %$ids) {
6955 next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1);
c4c844ef 6956 next if !$ids->{$sid}->{content}->{images};
335af808
DM
6957 push @$res, $sid;
6958 }
6959
6960 return $res;
6961}
6962
1e3baf05 69631;