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