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