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