]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
check for $vga->{type} instead of $vga
[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;
c9db2240 661my $MAX_UNUSED_DISKS = 256;
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;
daadd5a4 2019
55655ebc 2020 if ($q35 && $vgaid eq 'vga') {
daadd5a4 2021 # the first display uses pcie.0 bus on q35 machines
55655ebc
DC
2022 $pciaddr = print_pcie_addr($vgaid, $bridges);
2023 } else {
2024 $pciaddr = print_pci_addr($vgaid, $bridges);
2025 }
2026
2027 return "$type,id=${vgaid}${memory}${pciaddr}";
2028}
2029
9ed7a77c
WB
2030sub drive_is_cloudinit {
2031 my ($drive) = @_;
2032 return $drive->{file} =~ m@[:/]vm-\d+-cloudinit(?:\.$QEMU_FORMAT_RE)?$@;
2033}
2034
1e3baf05 2035sub drive_is_cdrom {
9c52f5ed
WB
2036 my ($drive, $exclude_cloudinit) = @_;
2037
9ed7a77c 2038 return 0 if $exclude_cloudinit && drive_is_cloudinit($drive);
1e3baf05
DM
2039
2040 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
2041
2042}
2043
ffc0d8c7
WB
2044sub parse_number_sets {
2045 my ($set) = @_;
2046 my $res = [];
2047 foreach my $part (split(/;/, $set)) {
2048 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
2049 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
2050 push @$res, [ $1, $2 ];
2ed5d572 2051 } else {
ffc0d8c7 2052 die "invalid range: $part\n";
2ed5d572
AD
2053 }
2054 }
ffc0d8c7
WB
2055 return $res;
2056}
2ed5d572 2057
ffc0d8c7
WB
2058sub parse_numa {
2059 my ($data) = @_;
2060
2061 my $res = PVE::JSONSchema::parse_property_string($numa_fmt, $data);
2062 $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
2063 $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
2ed5d572
AD
2064 return $res;
2065}
2066
040b06b7
DA
2067sub parse_hostpci {
2068 my ($value) = @_;
2069
2070 return undef if !$value;
2071
1f4f447b 2072 my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
0cea6a01 2073
1f4f447b
WB
2074 my @idlist = split(/;/, $res->{host});
2075 delete $res->{host};
2076 foreach my $id (@idlist) {
2077 if ($id =~ /^$PCIRE$/) {
a3139f90
WB
2078 if (defined($2)) {
2079 push @{$res->{pciid}}, { id => $1, function => $2 };
2080 } else {
2081 my $pcidevices = lspci($1);
2082 $res->{pciid} = $pcidevices->{$1};
2083 }
0cea6a01 2084 } else {
1f4f447b
WB
2085 # should have been caught by parse_property_string already
2086 die "failed to parse PCI id: $id\n";
0cea6a01 2087 }
040b06b7 2088 }
040b06b7
DA
2089 return $res;
2090}
2091
1e3baf05
DM
2092# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
2093sub parse_net {
2094 my ($data) = @_;
2095
cd9c34d1
WB
2096 my $res = eval { PVE::JSONSchema::parse_property_string($net_fmt, $data) };
2097 if ($@) {
2098 warn $@;
2099 return undef;
1e3baf05 2100 }
b5b99790
WB
2101 if (!defined($res->{macaddr})) {
2102 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
2103 $res->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
2104 }
0c9a7596
AD
2105 return $res;
2106}
2107
2108# ipconfigX ip=cidr,gw=ip,ip6=cidr,gw6=ip
2109sub parse_ipconfig {
2110 my ($data) = @_;
2111
2112 my $res = eval { PVE::JSONSchema::parse_property_string($ipconfig_fmt, $data) };
2113 if ($@) {
2114 warn $@;
2115 return undef;
2116 }
2117
2118 if ($res->{gw} && !$res->{ip}) {
2119 warn 'gateway specified without specifying an IP address';
2120 return undef;
2121 }
2122 if ($res->{gw6} && !$res->{ip6}) {
2123 warn 'IPv6 gateway specified without specifying an IPv6 address';
2124 return undef;
2125 }
2126 if ($res->{gw} && $res->{ip} eq 'dhcp') {
2127 warn 'gateway specified together with DHCP';
2128 return undef;
2129 }
2130 if ($res->{gw6} && $res->{ip6} !~ /^$IPV6RE/) {
2131 # gw6 + auto/dhcp
2132 warn "IPv6 gateway specified together with $res->{ip6} address";
2133 return undef;
2134 }
2135
2136 if (!$res->{ip} && !$res->{ip6}) {
2137 return { ip => 'dhcp', ip6 => 'dhcp' };
2138 }
2139
1e3baf05
DM
2140 return $res;
2141}
2142
2143sub print_net {
2144 my $net = shift;
2145
cd9c34d1 2146 return PVE::JSONSchema::print_property_string($net, $net_fmt);
1e3baf05
DM
2147}
2148
2149sub add_random_macs {
2150 my ($settings) = @_;
2151
2152 foreach my $opt (keys %$settings) {
2153 next if $opt !~ m/^net(\d+)$/;
2154 my $net = parse_net($settings->{$opt});
2155 next if !$net;
2156 $settings->{$opt} = print_net($net);
2157 }
2158}
2159
055d554d
DM
2160sub vm_is_volid_owner {
2161 my ($storecfg, $vmid, $volid) = @_;
2162
2163 if ($volid !~ m|^/|) {
2164 my ($path, $owner);
2165 eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
2166 if ($owner && ($owner == $vmid)) {
2167 return 1;
2168 }
2169 }
2170
2171 return undef;
2172}
2173
3dc38fbb
WB
2174sub split_flagged_list {
2175 my $text = shift || '';
2176 $text =~ s/[,;]/ /g;
2177 $text =~ s/^\s+//;
2178 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
2179}
2180
2181sub join_flagged_list {
2182 my ($how, $lst) = @_;
2183 join $how, map { $lst->{$_} . $_ } keys %$lst;
2184}
2185
055d554d 2186sub vmconfig_delete_pending_option {
3dc38fbb 2187 my ($conf, $key, $force) = @_;
055d554d
DM
2188
2189 delete $conf->{pending}->{$key};
3dc38fbb
WB
2190 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
2191 $pending_delete_hash->{$key} = $force ? '!' : '';
2192 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
2193}
2194
2195sub vmconfig_undelete_pending_option {
2196 my ($conf, $key) = @_;
2197
3dc38fbb 2198 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
055d554d
DM
2199 delete $pending_delete_hash->{$key};
2200
3dc38fbb
WB
2201 if (%$pending_delete_hash) {
2202 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
2203 } else {
2204 delete $conf->{pending}->{delete};
2205 }
2206}
2207
2208sub vmconfig_register_unused_drive {
2209 my ($storecfg, $vmid, $conf, $drive) = @_;
2210
2d9ddec5
WB
2211 if (drive_is_cloudinit($drive)) {
2212 eval { PVE::Storage::vdisk_free($storecfg, $drive->{file}) };
2213 warn $@ if $@;
2214 } elsif (!drive_is_cdrom($drive)) {
055d554d
DM
2215 my $volid = $drive->{file};
2216 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
8793d495 2217 PVE::QemuConfig->add_unused_volume($conf, $volid, $vmid);
055d554d
DM
2218 }
2219 }
2220}
2221
c750e90a
DM
2222sub vmconfig_cleanup_pending {
2223 my ($conf) = @_;
2224
2225 # remove pending changes when nothing changed
2226 my $changes;
2227 foreach my $opt (keys %{$conf->{pending}}) {
2228 if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq $conf->{$opt})) {
2229 $changes = 1;
2230 delete $conf->{pending}->{$opt};
2231 }
2232 }
2233
3dc38fbb 2234 my $current_delete_hash = split_flagged_list($conf->{pending}->{delete});
c750e90a 2235 my $pending_delete_hash = {};
3dc38fbb 2236 while (my ($opt, $force) = each %$current_delete_hash) {
c750e90a 2237 if (defined($conf->{$opt})) {
3dc38fbb 2238 $pending_delete_hash->{$opt} = $force;
c750e90a
DM
2239 } else {
2240 $changes = 1;
2241 }
2242 }
2243
3dc38fbb
WB
2244 if (%$pending_delete_hash) {
2245 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
c750e90a
DM
2246 } else {
2247 delete $conf->{pending}->{delete};
2248 }
2249
2250 return $changes;
2251}
2252
bd27e851 2253# smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
ff6ffe20 2254my $smbios1_fmt = {
bd27e851
WB
2255 uuid => {
2256 type => 'string',
2257 pattern => '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
2258 format_description => 'UUID',
52261945 2259 description => "Set SMBIOS1 UUID.",
bd27e851
WB
2260 optional => 1,
2261 },
2262 version => {
2263 type => 'string',
2264 pattern => '\S+',
7f694a71 2265 format_description => 'string',
52261945 2266 description => "Set SMBIOS1 version.",
bd27e851
WB
2267 optional => 1,
2268 },
2269 serial => {
2270 type => 'string',
2271 pattern => '\S+',
7f694a71 2272 format_description => 'string',
52261945 2273 description => "Set SMBIOS1 serial number.",
bd27e851
WB
2274 optional => 1,
2275 },
2276 manufacturer => {
2277 type => 'string',
2278 pattern => '\S+',
7f694a71 2279 format_description => 'string',
52261945 2280 description => "Set SMBIOS1 manufacturer.",
bd27e851
WB
2281 optional => 1,
2282 },
2283 product => {
2284 type => 'string',
2285 pattern => '\S+',
7f694a71 2286 format_description => 'string',
52261945 2287 description => "Set SMBIOS1 product ID.",
bd27e851
WB
2288 optional => 1,
2289 },
2290 sku => {
2291 type => 'string',
2292 pattern => '\S+',
7f694a71 2293 format_description => 'string',
52261945 2294 description => "Set SMBIOS1 SKU string.",
bd27e851
WB
2295 optional => 1,
2296 },
2297 family => {
2298 type => 'string',
2299 pattern => '\S+',
7f694a71 2300 format_description => 'string',
52261945 2301 description => "Set SMBIOS1 family string.",
bd27e851
WB
2302 optional => 1,
2303 },
2796e7d5
DM
2304};
2305
2796e7d5
DM
2306sub parse_smbios1 {
2307 my ($data) = @_;
2308
ff6ffe20 2309 my $res = eval { PVE::JSONSchema::parse_property_string($smbios1_fmt, $data) };
bd27e851 2310 warn $@ if $@;
2796e7d5
DM
2311 return $res;
2312}
2313
cd11416f
DM
2314sub print_smbios1 {
2315 my ($smbios1) = @_;
ff6ffe20 2316 return PVE::JSONSchema::print_property_string($smbios1, $smbios1_fmt);
cd11416f
DM
2317}
2318
ff6ffe20 2319PVE::JSONSchema::register_format('pve-qm-smbios1', $smbios1_fmt);
2796e7d5 2320
1e3baf05
DM
2321PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
2322sub verify_bootdisk {
2323 my ($value, $noerr) = @_;
2324
74479ee9 2325 return $value if is_valid_drivename($value);
1e3baf05
DM
2326
2327 return undef if $noerr;
2328
2329 die "invalid boot disk '$value'\n";
2330}
2331
0ea9541d
DM
2332sub parse_watchdog {
2333 my ($value) = @_;
2334
2335 return undef if !$value;
2336
ec3582b5
WB
2337 my $res = eval { PVE::JSONSchema::parse_property_string($watchdog_fmt, $value) };
2338 warn $@ if $@;
0ea9541d
DM
2339 return $res;
2340}
2341
9d66b397
SI
2342sub parse_guest_agent {
2343 my ($value) = @_;
2344
2345 return {} if !defined($value->{agent});
2346
2347 my $res = eval { PVE::JSONSchema::parse_property_string($agent_fmt, $value->{agent}) };
2348 warn $@ if $@;
2349
2350 # if the agent is disabled ignore the other potentially set properties
2351 return {} if !$res->{enabled};
2352 return $res;
2353}
2354
55655ebc
DC
2355sub parse_vga {
2356 my ($value) = @_;
2357
2358 return {} if !$value;
2359 my $res = eval { PVE::JSONSchema::parse_property_string($vga_fmt, $value) };
2360 warn $@ if $@;
2361 return $res;
2362}
2363
1e3baf05
DM
2364PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
2365sub verify_usb_device {
2366 my ($value, $noerr) = @_;
2367
2368 return $value if parse_usb_device($value);
2369
2370 return undef if $noerr;
19672434 2371
1e3baf05
DM
2372 die "unable to parse usb device\n";
2373}
2374
1e3baf05
DM
2375# add JSON properties for create and set function
2376sub json_config_properties {
2377 my $prop = shift;
2378
2379 foreach my $opt (keys %$confdesc) {
c6737ef1 2380 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' || $opt eq 'runningmachine';
1e3baf05
DM
2381 $prop->{$opt} = $confdesc->{$opt};
2382 }
2383
2384 return $prop;
2385}
2386
d41121fd
DM
2387# return copy of $confdesc_cloudinit to generate documentation
2388sub cloudinit_config_properties {
2389
2390 return dclone($confdesc_cloudinit);
2391}
2392
1e3baf05
DM
2393sub check_type {
2394 my ($key, $value) = @_;
2395
2396 die "unknown setting '$key'\n" if !$confdesc->{$key};
2397
2398 my $type = $confdesc->{$key}->{type};
2399
6b64503e 2400 if (!defined($value)) {
1e3baf05
DM
2401 die "got undefined value\n";
2402 }
2403
2404 if ($value =~ m/[\n\r]/) {
2405 die "property contains a line feed\n";
2406 }
2407
2408 if ($type eq 'boolean') {
19672434
DM
2409 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2410 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2411 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
2412 } elsif ($type eq 'integer') {
2413 return int($1) if $value =~ m/^(\d+)$/;
2414 die "type check ('integer') failed - got '$value'\n";
04432191
AD
2415 } elsif ($type eq 'number') {
2416 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2417 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
2418 } elsif ($type eq 'string') {
2419 if (my $fmt = $confdesc->{$key}->{format}) {
1e3baf05 2420 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
2421 return $value;
2422 }
1e3baf05 2423 $value =~ s/^\"(.*)\"$/$1/;
19672434 2424 return $value;
1e3baf05
DM
2425 } else {
2426 die "internal error"
2427 }
2428}
2429
040b06b7
DA
2430sub check_iommu_support{
2431 #fixme : need to check IOMMU support
2432 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2433
2434 my $iommu=1;
2435 return $iommu;
2436
2437}
2438
1e3baf05
DM
2439sub touch_config {
2440 my ($vmid) = @_;
2441
ffda963f 2442 my $conf = PVE::QemuConfig->config_file($vmid);
1e3baf05
DM
2443 utime undef, undef, $conf;
2444}
2445
1e3baf05 2446sub destroy_vm {
15cc8784 2447 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1e3baf05 2448
ffda963f 2449 my $conffile = PVE::QemuConfig->config_file($vmid);
1e3baf05 2450
ffda963f 2451 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 2452
ffda963f 2453 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 2454
5e67a2d2
DC
2455 if ($conf->{template}) {
2456 # check if any base image is still used by a linked clone
2457 foreach_drive($conf, sub {
2458 my ($ds, $drive) = @_;
2459
2460 return if drive_is_cdrom($drive);
2461
2462 my $volid = $drive->{file};
2463
2464 return if !$volid || $volid =~ m|^/|;
2465
2466 die "base volume '$volid' is still in use by linked cloned\n"
2467 if PVE::Storage::volume_is_base_and_used($storecfg, $volid);
2468
2469 });
2470 }
2471
19672434 2472 # only remove disks owned by this VM
1e3baf05
DM
2473 foreach_drive($conf, sub {
2474 my ($ds, $drive) = @_;
2475
9c52f5ed 2476 return if drive_is_cdrom($drive, 1);
1e3baf05
DM
2477
2478 my $volid = $drive->{file};
ed221350 2479
ff1a2432 2480 return if !$volid || $volid =~ m|^/|;
1e3baf05 2481
6b64503e 2482 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 2483 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 2484
31b52247
FG
2485 eval {
2486 PVE::Storage::vdisk_free($storecfg, $volid);
2487 };
2488 warn "Could not remove disk '$volid', check manually: $@" if $@;
2489
1e3baf05 2490 });
19672434 2491
a6af7b3e 2492 if ($keep_empty_config) {
9c502e26 2493 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
2494 } else {
2495 unlink $conffile;
2496 }
1e3baf05
DM
2497
2498 # also remove unused disk
2499 eval {
6b64503e 2500 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
2501
2502 eval {
6b64503e 2503 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 2504 my ($volid, $sid, $volname, $d) = @_;
6b64503e 2505 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
2506 });
2507 };
2508 warn $@ if $@;
2509
2510 };
2511 warn $@ if $@;
2512}
2513
1e3baf05
DM
2514sub parse_vm_config {
2515 my ($filename, $raw) = @_;
2516
2517 return undef if !defined($raw);
2518
554ac7e7 2519 my $res = {
fc1ddcdc 2520 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 2521 snapshots => {},
0d732d16 2522 pending => {},
554ac7e7 2523 };
1e3baf05 2524
19672434 2525 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
2526 || die "got strange filename '$filename'";
2527
2528 my $vmid = $1;
2529
0d18dcfc 2530 my $conf = $res;
b0ec896e 2531 my $descr;
e297c490 2532 my $section = '';
0581fe4f 2533
0d18dcfc
DM
2534 my @lines = split(/\n/, $raw);
2535 foreach my $line (@lines) {
1e3baf05 2536 next if $line =~ m/^\s*$/;
be190583 2537
eab09f4e 2538 if ($line =~ m/^\[PENDING\]\s*$/i) {
e297c490 2539 $section = 'pending';
b0ec896e
DM
2540 if (defined($descr)) {
2541 $descr =~ s/\s+$//;
2542 $conf->{description} = $descr;
2543 }
2544 $descr = undef;
e297c490 2545 $conf = $res->{$section} = {};
eab09f4e
AD
2546 next;
2547
0d732d16 2548 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
e297c490 2549 $section = $1;
b0ec896e
DM
2550 if (defined($descr)) {
2551 $descr =~ s/\s+$//;
2552 $conf->{description} = $descr;
2553 }
2554 $descr = undef;
e297c490 2555 $conf = $res->{snapshots}->{$section} = {};
0d18dcfc
DM
2556 next;
2557 }
1e3baf05 2558
0581fe4f 2559 if ($line =~ m/^\#(.*)\s*$/) {
b0ec896e 2560 $descr = '' if !defined($descr);
0581fe4f
DM
2561 $descr .= PVE::Tools::decode_text($1) . "\n";
2562 next;
2563 }
2564
1e3baf05 2565 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
b0ec896e 2566 $descr = '' if !defined($descr);
0581fe4f 2567 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
2568 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2569 $conf->{snapstate} = $1;
1e3baf05
DM
2570 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2571 my $key = $1;
2572 my $value = $2;
0d18dcfc 2573 $conf->{$key} = $value;
ef824322 2574 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
e297c490 2575 my $value = $1;
ef824322
DM
2576 if ($section eq 'pending') {
2577 $conf->{delete} = $value; # we parse this later
2578 } else {
2579 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
eab09f4e 2580 }
15cf7698 2581 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(.+?)\s*$/) {
1e3baf05
DM
2582 my $key = $1;
2583 my $value = $2;
2584 eval { $value = check_type($key, $value); };
2585 if ($@) {
2586 warn "vm $vmid - unable to parse value of '$key' - $@";
2587 } else {
b799312f 2588 $key = 'ide2' if $key eq 'cdrom';
1e3baf05 2589 my $fmt = $confdesc->{$key}->{format};
b799312f 2590 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
1e3baf05
DM
2591 my $v = parse_drive($key, $value);
2592 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
2593 $v->{file} = $volid;
6b64503e 2594 $value = print_drive($vmid, $v);
1e3baf05
DM
2595 } else {
2596 warn "vm $vmid - unable to parse value of '$key'\n";
2597 next;
2598 }
2599 }
2600
b799312f 2601 $conf->{$key} = $value;
1e3baf05
DM
2602 }
2603 }
2604 }
2605
b0ec896e
DM
2606 if (defined($descr)) {
2607 $descr =~ s/\s+$//;
2608 $conf->{description} = $descr;
2609 }
0d18dcfc 2610 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
2611
2612 return $res;
2613}
2614
1858638f
DM
2615sub write_vm_config {
2616 my ($filename, $conf) = @_;
1e3baf05 2617
0d18dcfc
DM
2618 delete $conf->{snapstate}; # just to be sure
2619
1858638f
DM
2620 if ($conf->{cdrom}) {
2621 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
2622 $conf->{ide2} = $conf->{cdrom};
2623 delete $conf->{cdrom};
2624 }
1e3baf05
DM
2625
2626 # we do not use 'smp' any longer
1858638f
DM
2627 if ($conf->{sockets}) {
2628 delete $conf->{smp};
2629 } elsif ($conf->{smp}) {
2630 $conf->{sockets} = $conf->{smp};
2631 delete $conf->{cores};
2632 delete $conf->{smp};
1e3baf05
DM
2633 }
2634
ee2f90b1 2635 my $used_volids = {};
0d18dcfc 2636
ee2f90b1 2637 my $cleanup_config = sub {
ef824322 2638 my ($cref, $pending, $snapname) = @_;
1858638f 2639
ee2f90b1
DM
2640 foreach my $key (keys %$cref) {
2641 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
ef824322 2642 $key eq 'snapstate' || $key eq 'pending';
ee2f90b1 2643 my $value = $cref->{$key};
ef824322
DM
2644 if ($key eq 'delete') {
2645 die "propertry 'delete' is only allowed in [PENDING]\n"
2646 if !$pending;
2647 # fixme: check syntax?
2648 next;
2649 }
ee2f90b1
DM
2650 eval { $value = check_type($key, $value); };
2651 die "unable to parse value of '$key' - $@" if $@;
1858638f 2652
ee2f90b1
DM
2653 $cref->{$key} = $value;
2654
74479ee9 2655 if (!$snapname && is_valid_drivename($key)) {
ed221350 2656 my $drive = parse_drive($key, $value);
ee2f90b1
DM
2657 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
2658 }
1e3baf05 2659 }
ee2f90b1
DM
2660 };
2661
2662 &$cleanup_config($conf);
ef824322
DM
2663
2664 &$cleanup_config($conf->{pending}, 1);
2665
ee2f90b1 2666 foreach my $snapname (keys %{$conf->{snapshots}}) {
ef824322
DM
2667 die "internal error" if $snapname eq 'pending';
2668 &$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
1e3baf05
DM
2669 }
2670
1858638f
DM
2671 # remove 'unusedX' settings if we re-add a volume
2672 foreach my $key (keys %$conf) {
2673 my $value = $conf->{$key};
ee2f90b1 2674 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 2675 delete $conf->{$key};
1e3baf05 2676 }
1858638f 2677 }
be190583 2678
0d18dcfc 2679 my $generate_raw_config = sub {
b0ec896e 2680 my ($conf, $pending) = @_;
0581fe4f 2681
0d18dcfc
DM
2682 my $raw = '';
2683
2684 # add description as comment to top of file
b0ec896e
DM
2685 if (defined(my $descr = $conf->{description})) {
2686 if ($descr) {
2687 foreach my $cl (split(/\n/, $descr)) {
2688 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
2689 }
2690 } else {
2691 $raw .= "#\n" if $pending;
2692 }
0d18dcfc
DM
2693 }
2694
2695 foreach my $key (sort keys %$conf) {
ef824322 2696 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
0d18dcfc
DM
2697 $raw .= "$key: $conf->{$key}\n";
2698 }
2699 return $raw;
2700 };
0581fe4f 2701
0d18dcfc 2702 my $raw = &$generate_raw_config($conf);
ef824322
DM
2703
2704 if (scalar(keys %{$conf->{pending}})){
2705 $raw .= "\n[PENDING]\n";
b0ec896e 2706 $raw .= &$generate_raw_config($conf->{pending}, 1);
ef824322
DM
2707 }
2708
0d18dcfc
DM
2709 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
2710 $raw .= "\n[$snapname]\n";
2711 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 2712 }
1e3baf05 2713
1858638f
DM
2714 return $raw;
2715}
1e3baf05 2716
19672434 2717sub load_defaults {
1e3baf05
DM
2718
2719 my $res = {};
2720
2721 # we use static defaults from our JSON schema configuration
2722 foreach my $key (keys %$confdesc) {
2723 if (defined(my $default = $confdesc->{$key}->{default})) {
2724 $res->{$key} = $default;
2725 }
2726 }
19672434 2727
1e3baf05
DM
2728 return $res;
2729}
2730
2731sub config_list {
2732 my $vmlist = PVE::Cluster::get_vmlist();
2733 my $res = {};
2734 return $res if !$vmlist || !$vmlist->{ids};
2735 my $ids = $vmlist->{ids};
2736
1e3baf05
DM
2737 foreach my $vmid (keys %$ids) {
2738 my $d = $ids->{$vmid};
2739 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 2740 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
2741 $res->{$vmid}->{exists} = 1;
2742 }
2743 return $res;
2744}
2745
64e13401
DM
2746# test if VM uses local resources (to prevent migration)
2747sub check_local_resources {
2748 my ($conf, $noerr) = @_;
2749
2750 my $loc_res = 0;
19672434 2751
e0ab7331
DM
2752 $loc_res = 1 if $conf->{hostusb}; # old syntax
2753 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 2754
0d29ab3b 2755 foreach my $k (keys %$conf) {
49ca581d 2756 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
d44712fc
EK
2757 # sockets are safe: they will recreated be on the target side post-migrate
2758 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2fe1a152 2759 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
2760 }
2761
2762 die "VM uses local resources\n" if $loc_res && !$noerr;
2763
2764 return $loc_res;
2765}
2766
719893a9 2767# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
2768sub check_storage_availability {
2769 my ($storecfg, $conf, $node) = @_;
2770
2771 foreach_drive($conf, sub {
2772 my ($ds, $drive) = @_;
2773
2774 my $volid = $drive->{file};
2775 return if !$volid;
2776
2777 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2778 return if !$sid;
2779
2780 # check if storage is available on both nodes
2781 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
2782 PVE::Storage::storage_check_node($storecfg, $sid, $node);
2783 });
2784}
2785
719893a9
DM
2786# list nodes where all VM images are available (used by has_feature API)
2787sub shared_nodes {
2788 my ($conf, $storecfg) = @_;
2789
2790 my $nodelist = PVE::Cluster::get_nodelist();
2791 my $nodehash = { map { $_ => 1 } @$nodelist };
2792 my $nodename = PVE::INotify::nodename();
be190583 2793
719893a9
DM
2794 foreach_drive($conf, sub {
2795 my ($ds, $drive) = @_;
2796
2797 my $volid = $drive->{file};
2798 return if !$volid;
2799
2800 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2801 if ($storeid) {
2802 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
2803 if ($scfg->{disable}) {
2804 $nodehash = {};
2805 } elsif (my $avail = $scfg->{nodes}) {
2806 foreach my $node (keys %$nodehash) {
2807 delete $nodehash->{$node} if !$avail->{$node};
2808 }
2809 } elsif (!$scfg->{shared}) {
2810 foreach my $node (keys %$nodehash) {
2811 delete $nodehash->{$node} if $node ne $nodename
2812 }
2813 }
2814 }
2815 });
2816
2817 return $nodehash
2818}
2819
1e3baf05
DM
2820sub check_cmdline {
2821 my ($pidfile, $pid) = @_;
2822
6b64503e
DM
2823 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
2824 if (defined($fh)) {
1e3baf05
DM
2825 my $line = <$fh>;
2826 $fh->close;
2827 return undef if !$line;
6b64503e 2828 my @param = split(/\0/, $line);
1e3baf05
DM
2829
2830 my $cmd = $param[0];
06094efd 2831 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
1e3baf05
DM
2832
2833 for (my $i = 0; $i < scalar (@param); $i++) {
2834 my $p = $param[$i];
2835 next if !$p;
2836 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2837 my $p = $param[$i+1];
2838 return 1 if $p && ($p eq $pidfile);
2839 return undef;
2840 }
2841 }
2842 }
2843 return undef;
2844}
2845
2846sub check_running {
7e8dcf2c 2847 my ($vmid, $nocheck, $node) = @_;
1e3baf05 2848
ffda963f 2849 my $filename = PVE::QemuConfig->config_file($vmid, $node);
1e3baf05
DM
2850
2851 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 2852 if !$nocheck && ! -f $filename;
1e3baf05 2853
e6c3b671 2854 my $pidfile = pidfile_name($vmid);
1e3baf05 2855
e6c3b671
DM
2856 if (my $fd = IO::File->new("<$pidfile")) {
2857 my $st = stat($fd);
1e3baf05 2858 my $line = <$fd>;
6b64503e 2859 close($fd);
1e3baf05
DM
2860
2861 my $mtime = $st->mtime;
2862 if ($mtime > time()) {
2863 warn "file '$filename' modified in future\n";
2864 }
2865
2866 if ($line =~ m/^(\d+)$/) {
2867 my $pid = $1;
e6c3b671
DM
2868 if (check_cmdline($pidfile, $pid)) {
2869 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
2870 return $pid;
2871 }
2872 }
1e3baf05
DM
2873 }
2874 }
2875
2876 return undef;
2877}
2878
2879sub vzlist {
19672434 2880
1e3baf05
DM
2881 my $vzlist = config_list();
2882
6b64503e 2883 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 2884
19672434 2885 while (defined(my $de = $fd->read)) {
1e3baf05
DM
2886 next if $de !~ m/^(\d+)\.pid$/;
2887 my $vmid = $1;
6b64503e
DM
2888 next if !defined($vzlist->{$vmid});
2889 if (my $pid = check_running($vmid)) {
1e3baf05
DM
2890 $vzlist->{$vmid}->{pid} = $pid;
2891 }
2892 }
2893
2894 return $vzlist;
2895}
2896
1e3baf05
DM
2897sub disksize {
2898 my ($storecfg, $conf) = @_;
2899
2900 my $bootdisk = $conf->{bootdisk};
2901 return undef if !$bootdisk;
74479ee9 2902 return undef if !is_valid_drivename($bootdisk);
1e3baf05
DM
2903
2904 return undef if !$conf->{$bootdisk};
2905
2906 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
2907 return undef if !defined($drive);
2908
2909 return undef if drive_is_cdrom($drive);
2910
2911 my $volid = $drive->{file};
2912 return undef if !$volid;
2913
24afaca0 2914 return $drive->{size};
1e3baf05
DM
2915}
2916
b1a70cab
DM
2917our $vmstatus_return_properties = {
2918 vmid => get_standard_option('pve-vmid'),
2919 status => {
2920 description => "Qemu process status.",
2921 type => 'string',
2922 enum => ['stopped', 'running'],
2923 },
2924 maxmem => {
2925 description => "Maximum memory in bytes.",
2926 type => 'integer',
2927 optional => 1,
2928 renderer => 'bytes',
2929 },
2930 maxdisk => {
2931 description => "Root disk size in bytes.",
2932 type => 'integer',
2933 optional => 1,
2934 renderer => 'bytes',
2935 },
2936 name => {
2937 description => "VM name.",
2938 type => 'string',
2939 optional => 1,
2940 },
2941 qmpstatus => {
2942 description => "Qemu QMP agent status.",
2943 type => 'string',
2944 optional => 1,
2945 },
2946 pid => {
2947 description => "PID of running qemu process.",
2948 type => 'integer',
2949 optional => 1,
2950 },
2951 uptime => {
2952 description => "Uptime.",
2953 type => 'integer',
2954 optional => 1,
2955 renderer => 'duration',
2956 },
2957 cpus => {
2958 description => "Maximum usable CPUs.",
2959 type => 'number',
2960 optional => 1,
2961 },
2962};
2963
1e3baf05
DM
2964my $last_proc_pid_stat;
2965
03a33f30
DM
2966# get VM status information
2967# This must be fast and should not block ($full == false)
2968# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2969sub vmstatus {
03a33f30 2970 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2971
2972 my $res = {};
2973
19672434 2974 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2975
2976 my $list = vzlist();
3618ee99
EK
2977 my $defaults = load_defaults();
2978
694fcad4 2979 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 2980
ae4915a2
DM
2981 my $cpucount = $cpuinfo->{cpus} || 1;
2982
1e3baf05
DM
2983 foreach my $vmid (keys %$list) {
2984 next if $opt_vmid && ($vmid ne $opt_vmid);
2985
ffda963f 2986 my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
1e3baf05
DM
2987 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
2988
b1a70cab 2989 my $d = { vmid => $vmid };
1e3baf05
DM
2990 $d->{pid} = $list->{$vmid}->{pid};
2991
2992 # fixme: better status?
2993 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
2994
af990afe
DM
2995 my $size = disksize($storecfg, $conf);
2996 if (defined($size)) {
2997 $d->{disk} = 0; # no info available
1e3baf05
DM
2998 $d->{maxdisk} = $size;
2999 } else {
3000 $d->{disk} = 0;
3001 $d->{maxdisk} = 0;
3002 }
3003
3618ee99
EK
3004 $d->{cpus} = ($conf->{sockets} || $defaults->{sockets})
3005 * ($conf->{cores} || $defaults->{cores});
ae4915a2 3006 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
d7c8364b 3007 $d->{cpus} = $conf->{vcpus} if $conf->{vcpus};
ae4915a2 3008
1e3baf05 3009 $d->{name} = $conf->{name} || "VM $vmid";
3618ee99
EK
3010 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024)
3011 : $defaults->{memory}*(1024*1024);
1e3baf05 3012
8b1accf7 3013 if ($conf->{balloon}) {
4bdb0514 3014 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
3618ee99
EK
3015 $d->{shares} = defined($conf->{shares}) ? $conf->{shares}
3016 : $defaults->{shares};
8b1accf7
DM
3017 }
3018
1e3baf05
DM
3019 $d->{uptime} = 0;
3020 $d->{cpu} = 0;
1e3baf05
DM
3021 $d->{mem} = 0;
3022
3023 $d->{netout} = 0;
3024 $d->{netin} = 0;
3025
3026 $d->{diskread} = 0;
3027 $d->{diskwrite} = 0;
3028
ffda963f 3029 $d->{template} = PVE::QemuConfig->is_template($conf);
4d8c851b 3030
8107b378
DC
3031 $d->{serial} = 1 if conf_has_serial($conf);
3032
1e3baf05
DM
3033 $res->{$vmid} = $d;
3034 }
3035
3036 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
3037 foreach my $dev (keys %$netdev) {
3038 next if $dev !~ m/^tap([1-9]\d*)i/;
3039 my $vmid = $1;
3040 my $d = $res->{$vmid};
3041 next if !$d;
19672434 3042
1e3baf05
DM
3043 $d->{netout} += $netdev->{$dev}->{receive};
3044 $d->{netin} += $netdev->{$dev}->{transmit};
604ea644
AD
3045
3046 if ($full) {
3047 $d->{nics}->{$dev}->{netout} = $netdev->{$dev}->{receive};
3048 $d->{nics}->{$dev}->{netin} = $netdev->{$dev}->{transmit};
3049 }
3050
1e3baf05
DM
3051 }
3052
1e3baf05
DM
3053 my $ctime = gettimeofday;
3054
3055 foreach my $vmid (keys %$list) {
3056
3057 my $d = $res->{$vmid};
3058 my $pid = $d->{pid};
3059 next if !$pid;
3060
694fcad4
DM
3061 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
3062 next if !$pstat; # not running
19672434 3063
694fcad4 3064 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 3065
694fcad4 3066 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 3067
694fcad4 3068 if ($pstat->{vsize}) {
6b64503e 3069 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
3070 }
3071
3072 my $old = $last_proc_pid_stat->{$pid};
3073 if (!$old) {
19672434
DM
3074 $last_proc_pid_stat->{$pid} = {
3075 time => $ctime,
1e3baf05
DM
3076 used => $used,
3077 cpu => 0,
1e3baf05
DM
3078 };
3079 next;
3080 }
3081
7f0b5beb 3082 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
3083
3084 if ($dtime > 1000) {
3085 my $dutime = $used - $old->{used};
3086
ae4915a2 3087 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 3088 $last_proc_pid_stat->{$pid} = {
19672434 3089 time => $ctime,
1e3baf05
DM
3090 used => $used,
3091 cpu => $d->{cpu},
1e3baf05
DM
3092 };
3093 } else {
3094 $d->{cpu} = $old->{cpu};
1e3baf05
DM
3095 }
3096 }
3097
f5eb281a 3098 return $res if !$full;
03a33f30
DM
3099
3100 my $qmpclient = PVE::QMPClient->new();
3101
64e7fcf2
DM
3102 my $ballooncb = sub {
3103 my ($vmid, $resp) = @_;
3104
3105 my $info = $resp->{'return'};
38babf81
DM
3106 return if !$info->{max_mem};
3107
64e7fcf2
DM
3108 my $d = $res->{$vmid};
3109
38babf81
DM
3110 # use memory assigned to VM
3111 $d->{maxmem} = $info->{max_mem};
3112 $d->{balloon} = $info->{actual};
3113
3114 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
3115 $d->{mem} = $info->{total_mem} - $info->{free_mem};
3116 $d->{freemem} = $info->{free_mem};
64e7fcf2
DM
3117 }
3118
604ea644 3119 $d->{ballooninfo} = $info;
64e7fcf2
DM
3120 };
3121
03a33f30
DM
3122 my $blockstatscb = sub {
3123 my ($vmid, $resp) = @_;
3124 my $data = $resp->{'return'} || [];
3125 my $totalrdbytes = 0;
3126 my $totalwrbytes = 0;
604ea644 3127
03a33f30
DM
3128 for my $blockstat (@$data) {
3129 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
3130 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
604ea644
AD
3131
3132 $blockstat->{device} =~ s/drive-//;
3133 $res->{$vmid}->{blockstat}->{$blockstat->{device}} = $blockstat->{stats};
03a33f30
DM
3134 }
3135 $res->{$vmid}->{diskread} = $totalrdbytes;
3136 $res->{$vmid}->{diskwrite} = $totalwrbytes;
3137 };
3138
3139 my $statuscb = sub {
3140 my ($vmid, $resp) = @_;
64e7fcf2 3141
03a33f30 3142 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
3143 # this fails if ballon driver is not loaded, so this must be
3144 # the last commnand (following command are aborted if this fails).
38babf81 3145 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
3146
3147 my $status = 'unknown';
3148 if (!defined($status = $resp->{'return'}->{status})) {
3149 warn "unable to get VM status\n";
3150 return;
3151 }
3152
3153 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
3154 };
3155
3156 foreach my $vmid (keys %$list) {
3157 next if $opt_vmid && ($vmid ne $opt_vmid);
3158 next if !$res->{$vmid}->{pid}; # not running
3159 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
3160 }
3161
b017fbda 3162 $qmpclient->queue_execute(undef, 2);
03a33f30
DM
3163
3164 foreach my $vmid (keys %$list) {
3165 next if $opt_vmid && ($vmid ne $opt_vmid);
3166 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
3167 }
3168
1e3baf05
DM
3169 return $res;
3170}
3171
3172sub foreach_drive {
b74ff047 3173 my ($conf, $func, @param) = @_;
1e3baf05 3174
74479ee9
FG
3175 foreach my $ds (valid_drive_names()) {
3176 next if !defined($conf->{$ds});
1e3baf05 3177
6b64503e 3178 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
3179 next if !$drive;
3180
b74ff047 3181 &$func($ds, $drive, @param);
1e3baf05
DM
3182 }
3183}
3184
d5769dc2 3185sub foreach_volid {
b6adff33 3186 my ($conf, $func, @param) = @_;
be190583 3187
d5769dc2
DM
3188 my $volhash = {};
3189
3190 my $test_volid = sub {
ec82e3ee 3191 my ($volid, $is_cdrom, $replicate, $shared, $snapname) = @_;
d5769dc2
DM
3192
3193 return if !$volid;
be190583 3194
392f8b5d
DM
3195 $volhash->{$volid}->{cdrom} //= 1;
3196 $volhash->{$volid}->{cdrom} = 0 if !$is_cdrom;
3197
3198 $volhash->{$volid}->{replicate} //= 0;
3199 $volhash->{$volid}->{replicate} = 1 if $replicate;
39019f75 3200
ec82e3ee
CH
3201 $volhash->{$volid}->{shared} //= 0;
3202 $volhash->{$volid}->{shared} = 1 if $shared;
3203
39019f75
DM
3204 $volhash->{$volid}->{referenced_in_config} //= 0;
3205 $volhash->{$volid}->{referenced_in_config} = 1 if !defined($snapname);
3206
3207 $volhash->{$volid}->{referenced_in_snapshot}->{$snapname} = 1
3208 if defined($snapname);
d5769dc2
DM
3209 };
3210
ed221350 3211 foreach_drive($conf, sub {
d5769dc2 3212 my ($ds, $drive) = @_;
ec82e3ee 3213 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, undef);
d5769dc2
DM
3214 });
3215
3216 foreach my $snapname (keys %{$conf->{snapshots}}) {
3217 my $snap = $conf->{snapshots}->{$snapname};
39019f75 3218 $test_volid->($snap->{vmstate}, 0, 1, $snapname);
ed221350 3219 foreach_drive($snap, sub {
d5769dc2 3220 my ($ds, $drive) = @_;
ec82e3ee 3221 $test_volid->($drive->{file}, drive_is_cdrom($drive), $drive->{replicate} // 1, $drive->{shared}, $snapname);
d5769dc2
DM
3222 });
3223 }
3224
3225 foreach my $volid (keys %$volhash) {
b6adff33 3226 &$func($volid, $volhash->{$volid}, @param);
d5769dc2
DM
3227 }
3228}
3229
8107b378
DC
3230sub conf_has_serial {
3231 my ($conf) = @_;
3232
3233 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3234 if ($conf->{"serial$i"}) {
3235 return 1;
3236 }
3237 }
3238
3239 return 0;
3240}
3241
86b8228b
DM
3242sub vga_conf_has_spice {
3243 my ($vga) = @_;
3244
55655ebc
DC
3245 my $vgaconf = parse_vga($vga);
3246 my $vgatype = $vgaconf->{type};
3247 return 0 if !$vgatype || $vgatype !~ m/^qxl([234])?$/;
590e698c
DM
3248
3249 return $1 || 1;
86b8228b
DM
3250}
3251
1e3baf05 3252sub config_to_command {
67812f9c 3253 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
3254
3255 my $cmd = [];
8c559505
DM
3256 my $globalFlags = [];
3257 my $machineFlags = [];
3258 my $rtcFlags = [];
519ed28c 3259 my $cpuFlags = [];
5bdcf937 3260 my $devices = [];
b78ebef7 3261 my $pciaddr = '';
5bdcf937 3262 my $bridges = {};
1e3baf05
DM
3263 my $kvmver = kvm_user_version();
3264 my $vernum = 0; # unknown
b42d3cf9 3265 my $ostype = $conf->{ostype};
4317f69f 3266 my $winversion = windows_version($ostype);
74c02ef7 3267 my $kvm = $conf->{kvm} // 1;
4317f69f 3268
bfcd9b7e
PA
3269 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm} && $kvm);
3270
a3c52213
DM
3271 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
3272 $vernum = $1*1000000+$2*1000;
3273 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
3274 $vernum = $1*1000000+$2*1000+$3;
3275 }
3276
a3c52213 3277 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
3278
3279 my $have_ovz = -f '/proc/vz/vestat';
3280
db656e5f 3281 my $q35 = machine_type_is_q35($conf);
4d3f29ed 3282 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
23f73120 3283 my $machine_type = $forcemachine || $conf->{machine};
249c4a6c
AD
3284 my $use_old_bios_files = undef;
3285 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
db656e5f 3286
f08e17c7
AD
3287 my $cpuunits = defined($conf->{cpuunits}) ?
3288 $conf->{cpuunits} : $defaults->{cpuunits};
3289
1e3baf05
DM
3290 push @$cmd, '/usr/bin/kvm';
3291
3292 push @$cmd, '-id', $vmid;
3293
e4d4cda1
HR
3294 my $vmname = $conf->{name} || "vm$vmid";
3295
3296 push @$cmd, '-name', $vmname;
3297
1e3baf05
DM
3298 my $use_virtio = 0;
3299
c971c4f2
AD
3300 my $qmpsocket = qmp_socket($vmid);
3301 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
3302 push @$cmd, '-mon', "chardev=qmp,mode=control";
3303
71bd73b5
DC
3304 if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 12)) {
3305 my $eventsocket = qmp_socket($vmid, 0, 'event');
3306 push @$cmd, '-chardev', "socket,id=qmp-event,path=$eventsocket,server,nowait";
3307 push @$cmd, '-mon', "chardev=qmp-event,mode=control";
3308 }
1e3baf05 3309
6b64503e 3310 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 3311
1e3baf05
DM
3312 push @$cmd, '-daemonize';
3313
2796e7d5
DM
3314 if ($conf->{smbios1}) {
3315 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
3316 }
3317
6ee499ff
DC
3318 if ($conf->{vmgenid}) {
3319 push @$devices, '-device', 'vmgenid,guid='.$conf->{vmgenid};
3320 }
3321
3edb45e7 3322 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
4dcce9ee 3323 die "uefi base image not found\n" if ! -f $OVMF_CODE;
2ddc0a5c 3324
4dcce9ee 3325 my $path;
13bca7b4 3326 my $format;
4dcce9ee
TL
3327 if (my $efidisk = $conf->{efidisk0}) {
3328 my $d = PVE::JSONSchema::parse_property_string($efidisk_fmt, $efidisk);
2ddc0a5c 3329 my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
13bca7b4 3330 $format = $d->{format};
2ddc0a5c
DC
3331 if ($storeid) {
3332 $path = PVE::Storage::path($storecfg, $d->{file});
13bca7b4
WB
3333 if (!defined($format)) {
3334 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
3335 $format = qemu_img_format($scfg, $volname);
3336 }
2ddc0a5c
DC
3337 } else {
3338 $path = $d->{file};
13bca7b4
WB
3339 die "efidisk format must be specified\n"
3340 if !defined($format);
2ddc0a5c 3341 }
2ddc0a5c 3342 } else {
4dcce9ee
TL
3343 warn "no efidisk configured! Using temporary efivars disk.\n";
3344 $path = "/tmp/$vmid-ovmf.fd";
3345 PVE::Tools::file_copy($OVMF_VARS, $path, -s $OVMF_VARS);
13bca7b4 3346 $format = 'raw';
2ddc0a5c 3347 }
4dcce9ee
TL
3348
3349 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2bfbee03 3350 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
a783c78e
AD
3351 }
3352
da8b4189 3353
d40e5e18
DC
3354 # add usb controllers
3355 my @usbcontrollers = PVE::QemuServer::USB::get_usb_controllers($conf, $bridges, $q35, $usbdesc->{format}, $MAX_USB_DEVICES);
3356 push @$devices, @usbcontrollers if @usbcontrollers;
55655ebc 3357 my $vga = parse_vga($conf->{vga});
2fa3151e 3358
55655ebc
DC
3359 my $qxlnum = vga_conf_has_spice($conf->{vga});
3360 $vga->{type} = 'qxl' if $qxlnum;
2fa3151e 3361
55655ebc 3362 if (!$vga->{type}) {
a2a5cd64 3363 if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
55655ebc 3364 $vga->{type} = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
a2a5cd64 3365 } else {
55655ebc 3366 $vga->{type} = ($winversion >= 6) ? 'std' : 'cirrus';
a2a5cd64 3367 }
5acbfe9e
DM
3368 }
3369
1e3baf05 3370 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
3371 my $tablet;
3372 if (defined($conf->{tablet})) {
3373 $tablet = $conf->{tablet};
3374 } else {
3375 $tablet = $defaults->{tablet};
590e698c 3376 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
55655ebc 3377 $tablet = 0 if $vga->{type} =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
5acbfe9e
DM
3378 }
3379
db656e5f 3380 push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
b467f79a 3381
16a91d65 3382 my $kvm_off = 0;
4317f69f
AD
3383 my $gpu_passthrough;
3384
1e3baf05 3385 # host pci devices
040b06b7 3386 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2e3b7e2a
AD
3387 my $d = parse_hostpci($conf->{"hostpci$i"});
3388 next if !$d;
3389
3390 my $pcie = $d->{pcie};
3391 if($pcie){
3392 die "q35 machine model is not enabled" if !$q35;
3393 $pciaddr = print_pcie_addr("hostpci$i");
3394 }else{
3395 $pciaddr = print_pci_addr("hostpci$i", $bridges);
3396 }
3397
1f4f447b 3398 my $rombar = defined($d->{rombar}) && !$d->{rombar} ? ',rombar=0' : '';
9009150b 3399 my $romfile = $d->{romfile};
456a6fec 3400
1f4f447b
WB
3401 my $xvga = '';
3402 if ($d->{'x-vga'}) {
3403 $xvga = ',x-vga=on';
16a91d65 3404 $kvm_off = 1;
55655ebc 3405 $vga->{type} = 'none';
4317f69f
AD
3406 $gpu_passthrough = 1;
3407
230a4382
AD
3408 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
3409 $xvga = "";
3410 }
137483c0 3411 }
4543ecf0
AD
3412 my $pcidevices = $d->{pciid};
3413 my $multifunction = 1 if @$pcidevices > 1;
2e3b7e2a 3414
4543ecf0
AD
3415 my $j=0;
3416 foreach my $pcidevice (@$pcidevices) {
2e3b7e2a 3417
4543ecf0
AD
3418 my $id = "hostpci$i";
3419 $id .= ".$j" if $multifunction;
3420 my $addr = $pciaddr;
3421 $addr .= ".$j" if $multifunction;
6ea8cd3b 3422 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
4543ecf0
AD
3423
3424 if($j == 0){
3425 $devicestr .= "$rombar$xvga";
3426 $devicestr .= ",multifunction=on" if $multifunction;
456a6fec 3427 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
4543ecf0
AD
3428 }
3429
3430 push @$devices, '-device', $devicestr;
3431 $j++;
3432 }
1e3baf05
DM
3433 }
3434
3435 # usb devices
d40e5e18
DC
3436 my @usbdevices = PVE::QemuServer::USB::get_usb_devices($conf, $usbdesc->{format}, $MAX_USB_DEVICES);
3437 push @$devices, @usbdevices if @usbdevices;
1e3baf05 3438 # serial devices
bae179aa 3439 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 3440 if (my $path = $conf->{"serial$i"}) {
9f9d2fb2
DM
3441 if ($path eq 'socket') {
3442 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3443 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3444 push @$devices, '-device', "isa-serial,chardev=serial$i";
3445 } else {
3446 die "no such serial device\n" if ! -c $path;
3447 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3448 push @$devices, '-device', "isa-serial,chardev=serial$i";
3449 }
34978be3 3450 }
1e3baf05
DM
3451 }
3452
3453 # parallel devices
1989a89c 3454 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 3455 if (my $path = $conf->{"parallel$i"}) {
19672434 3456 die "no such parallel device\n" if ! -c $path;
32e69805 3457 my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
4c5dbaf6 3458 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
5bdcf937 3459 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 3460 }
1e3baf05
DM
3461 }
3462
19672434 3463
1e3baf05
DM
3464 my $sockets = 1;
3465 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3466 $sockets = $conf->{sockets} if $conf->{sockets};
3467
3468 my $cores = $conf->{cores} || 1;
3bd18e48 3469
de9d1e55 3470 my $maxcpus = $sockets * $cores;
76267728 3471
de9d1e55 3472 my $vcpus = $conf->{vcpus} ? $conf->{vcpus} : $maxcpus;
76267728 3473
de9d1e55
AD
3474 my $allowed_vcpus = $cpuinfo->{cpus};
3475
6965d5d1 3476 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
de9d1e55
AD
3477 if ($allowed_vcpus < $maxcpus);
3478
69c81430 3479 if($hotplug_features->{cpu} && qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 7)) {
1e3baf05 3480
69c81430
AD
3481 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3482 for (my $i = 2; $i <= $vcpus; $i++) {
3483 my $cpustr = print_cpu_device($conf,$i);
3484 push @$cmd, '-device', $cpustr;
3485 }
3486
3487 } else {
3488
3489 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3490 }
1e3baf05
DM
3491 push @$cmd, '-nodefaults';
3492
32baffb4 3493 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 3494
0888fdce
DM
3495 my $bootindex_hash = {};
3496 my $i = 1;
3497 foreach my $o (split(//, $bootorder)) {
3498 $bootindex_hash->{$o} = $i*100;
3499 $i++;
afdb31d5 3500 }
3b408e82 3501
dbea4415 3502 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
1e3baf05 3503
6b64503e 3504 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 3505
6b64503e 3506 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 3507
84902837 3508 if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga->{type} ne 'none'){
55655ebc 3509 push @$devices, '-device', print_vga_device($conf, $vga, undef, $qxlnum, $bridges);
b7be4ba9
AD
3510 my $socket = vnc_socket($vmid);
3511 push @$cmd, '-vnc', "unix:$socket,x509,password";
3512 } else {
55655ebc 3513 push @$cmd, '-vga', 'none' if $vga->{type} eq 'none';
b7be4ba9
AD
3514 push @$cmd, '-nographic';
3515 }
3516
1e3baf05 3517 # time drift fix
6b64503e 3518 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 3519
8c559505 3520 my $useLocaltime = $conf->{localtime};
1e3baf05 3521
4317f69f
AD
3522 if ($winversion >= 5) { # windows
3523 $useLocaltime = 1 if !defined($conf->{localtime});
7a131888 3524
4317f69f
AD
3525 # use time drift fix when acpi is enabled
3526 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
3527 $tdf = 1 if !defined($conf->{tdf});
462e8d19 3528 }
4317f69f 3529 }
462e8d19 3530
4317f69f
AD
3531 if ($winversion >= 6) {
3532 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3533 push @$cmd, '-no-hpet';
1e3baf05
DM
3534 }
3535
8c559505
DM
3536 push @$rtcFlags, 'driftfix=slew' if $tdf;
3537
74c02ef7 3538 if (!$kvm) {
8c559505 3539 push @$machineFlags, 'accel=tcg';
7f0b5beb 3540 }
1e3baf05 3541
952958bc
DM
3542 if ($machine_type) {
3543 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
3544 }
3545
8c559505
DM
3546 if ($conf->{startdate}) {
3547 push @$rtcFlags, "base=$conf->{startdate}";
3548 } elsif ($useLocaltime) {
3549 push @$rtcFlags, 'base=localtime';
3550 }
1e3baf05 3551
74c02ef7 3552 my $cpu = $kvm ? "kvm64" : "qemu64";
16a91d65 3553 if (my $cputype = $conf->{cpu}) {
ff6ffe20 3554 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
16a91d65
WB
3555 or die "Cannot parse cpu description: $cputype\n";
3556 $cpu = $cpuconf->{cputype};
3557 $kvm_off = 1 if $cpuconf->{hidden};
39fd79e2
WB
3558
3559 if (defined(my $flags = $cpuconf->{flags})) {
049fc9eb 3560 push @$cpuFlags, split(";", $flags);
39fd79e2 3561 }
16a91d65 3562 }
519ed28c 3563
4dc339e7
AD
3564 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3565
d853f40a
DM
3566 push @$cpuFlags , '-x2apic'
3567 if $conf->{ostype} && $conf->{ostype} eq 'solaris';
519ed28c 3568
2e1a5389
AD
3569 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3570
0dc48c3d
AD
3571 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3572
117a0414
AD
3573 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3574
74c02ef7
PA
3575 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3576 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
117a0414
AD
3577 }
3578
74c02ef7 3579 add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios}, $gpu_passthrough) if $kvm;
4317f69f 3580
74c02ef7 3581 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
dac7c619 3582
16a91d65
WB
3583 push @$cpuFlags, 'kvm=off' if $kvm_off;
3584
8930da74
DM
3585 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3586 die "internal error"; # should not happen
3587
3588 push @$cpuFlags, "vendor=${cpu_vendor}"
3589 if $cpu_vendor ne 'default';
3590
be190583 3591 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
519ed28c 3592
dac7c619 3593 push @$cmd, '-cpu', $cpu;
519ed28c 3594
0567a4d5
AD
3595 PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3596
1e3baf05
DM
3597 push @$cmd, '-S' if $conf->{freeze};
3598
b20df606 3599 push @$cmd, '-k', $conf->{keyboard} if defined($conf->{keyboard});
1e3baf05
DM
3600
3601 # enable sound
3602 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3603 #push @$cmd, '-soundhw', 'es1370';
3604 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 3605
9d66b397 3606 if (parse_guest_agent($conf)->{enabled}) {
7a6c2150 3607 my $qgasocket = qmp_socket($vmid, 1);
ab6a046f
AD
3608 my $pciaddr = print_pci_addr("qga0", $bridges);
3609 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3610 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3611 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3612 }
3613
1d794448 3614 my $spice_port;
2fa3151e 3615
590e698c
DM
3616 if ($qxlnum) {
3617 if ($qxlnum > 1) {
ac087616 3618 if ($winversion){
590e698c 3619 for(my $i = 1; $i < $qxlnum; $i++){
55655ebc 3620 push @$devices, '-device', print_vga_device($conf, $vga, $i, $qxlnum, $bridges);
590e698c
DM
3621 }
3622 } else {
3623 # assume other OS works like Linux
55655ebc
DC
3624 my ($ram, $vram) = ("134217728", "67108864");
3625 if ($vga->{memory}) {
3626 $ram = PVE::Tools::convert_size($qxlnum*4*$vga->{memory}, 'mb' => 'b');
3627 $vram = PVE::Tools::convert_size($qxlnum*2*$vga->{memory}, 'mb' => 'b');
3628 }
3629 push @$cmd, '-global', "qxl-vga.ram_size=$ram";
3630 push @$cmd, '-global', "qxl-vga.vram_size=$vram";
2fa3151e
AD
3631 }
3632 }
3633
1011b570 3634 my $pciaddr = print_pci_addr("spice", $bridges);
95a4b4a9 3635
af0eba7e
WB
3636 my $nodename = PVE::INotify::nodename();
3637 my $pfamily = PVE::Tools::get_host_address_family($nodename);
91152441
WB
3638 my @nodeaddrs = PVE::Tools::getaddrinfo_all('localhost', family => $pfamily);
3639 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3640 my $localhost = PVE::Network::addr_to_ip($nodeaddrs[0]->{addr});
3641 $spice_port = PVE::Tools::next_spice_port($pfamily, $localhost);
943340a6 3642
91152441 3643 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
1011b570 3644
d2da6d9b
AD
3645 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3646 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3647 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
1011b570
DM
3648 }
3649
8d9ae0d2
DM
3650 # enable balloon by default, unless explicitly disabled
3651 if (!defined($conf->{balloon}) || $conf->{balloon}) {
3652 $pciaddr = print_pci_addr("balloon0", $bridges);
3653 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3654 }
1e3baf05 3655
0ea9541d
DM
3656 if ($conf->{watchdog}) {
3657 my $wdopts = parse_watchdog($conf->{watchdog});
5bdcf937 3658 $pciaddr = print_pci_addr("watchdog", $bridges);
0a40e8ea 3659 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
3660 push @$devices, '-device', "$watchdog$pciaddr";
3661 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
3662 }
3663
1e3baf05 3664 my $vollist = [];
941e0c42 3665 my $scsicontroller = {};
26ee04b6 3666 my $ahcicontroller = {};
cdd20088 3667 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05 3668
5881b913
DM
3669 # Add iscsi initiator name if available
3670 if (my $initiator = get_initiator_name()) {
3671 push @$devices, '-iscsi', "initiator-name=$initiator";
3672 }
3673
1e3baf05
DM
3674 foreach_drive($conf, sub {
3675 my ($ds, $drive) = @_;
3676
ff1a2432 3677 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 3678 push @$vollist, $drive->{file};
ff1a2432 3679 }
afdb31d5 3680
4dcce9ee
TL
3681 # ignore efidisk here, already added in bios/fw handling code above
3682 return if $drive->{interface} eq 'efidisk';
3683
1e3baf05 3684 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
3685
3686 if (drive_is_cdrom ($drive)) {
3687 if ($bootindex_hash->{d}) {
3688 $drive->{bootindex} = $bootindex_hash->{d};
3689 $bootindex_hash->{d} += 1;
3690 }
3691 } else {
3692 if ($bootindex_hash->{c}) {
3693 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
3694 $bootindex_hash->{c} += 1;
3695 }
3696 }
3697
51f492cd
AD
3698 if($drive->{interface} eq 'virtio'){
3699 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread};
3700 }
3701
941e0c42 3702 if ($drive->{interface} eq 'scsi') {
cdd20088 3703
ee034f5c 3704 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
6731a4cf 3705
6731a4cf 3706 $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges);
a1b7d579 3707 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
fc8b40fd
AD
3708
3709 my $iothread = '';
3710 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{iothread}){
3711 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3712 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
e7a5104d
DC
3713 } elsif ($drive->{iothread}) {
3714 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
fc8b40fd
AD
3715 }
3716
6e11f143
AD
3717 my $queues = '';
3718 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{queues}){
3719 $queues = ",num_queues=$drive->{queues}";
3720 }
3721
3722 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
cdd20088 3723 $scsicontroller->{$controller}=1;
941e0c42 3724 }
3b408e82 3725
26ee04b6
DA
3726 if ($drive->{interface} eq 'sata') {
3727 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
5bdcf937
AD
3728 $pciaddr = print_pci_addr("ahci$controller", $bridges);
3729 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
3730 $ahcicontroller->{$controller}=1;
3731 }
46f58b5f 3732
15b21acc
MR
3733 my $drive_cmd = print_drive_full($storecfg, $vmid, $drive);
3734 push @$devices, '-drive',$drive_cmd;
46f58b5f 3735 push @$devices, '-device', print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
1e3baf05
DM
3736 });
3737
cc4d6182 3738 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 3739 next if !$conf->{"net$i"};
cc4d6182
DA
3740 my $d = parse_net($conf->{"net$i"});
3741 next if !$d;
1e3baf05 3742
cc4d6182 3743 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 3744
cc4d6182
DA
3745 if ($bootindex_hash->{n}) {
3746 $d->{bootindex} = $bootindex_hash->{n};
3747 $bootindex_hash->{n} += 1;
3748 }
1e3baf05 3749
cc4d6182 3750 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
5bdcf937
AD
3751 push @$devices, '-netdev', $netdevfull;
3752
ba9e1000 3753 my $netdevicefull = print_netdevice_full($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
5bdcf937
AD
3754 push @$devices, '-device', $netdevicefull;
3755 }
1e3baf05 3756
db656e5f
DM
3757 if (!$q35) {
3758 # add pci bridges
fc79e813
AD
3759 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3760 $bridges->{1} = 1;
3761 $bridges->{2} = 1;
3762 }
3763
6731a4cf
AD
3764 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3765
f8e83f05
AD
3766 while (my ($k, $v) = each %$bridges) {
3767 $pciaddr = print_pci_addr("pci.$k");
3768 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3769 }
19672434
DM
3770 }
3771
1e3baf05
DM
3772 # add custom args
3773 if ($conf->{args}) {
3ada46c9 3774 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
3775 push @$cmd, @$aa;
3776 }
3777
5bdcf937 3778 push @$cmd, @$devices;
be190583 3779 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 3780 if scalar(@$rtcFlags);
be190583 3781 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
3782 if scalar(@$machineFlags);
3783 push @$cmd, '-global', join(',', @$globalFlags)
3784 if scalar(@$globalFlags);
3785
1d794448 3786 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
1e3baf05 3787}
19672434 3788
1e3baf05
DM
3789sub vnc_socket {
3790 my ($vmid) = @_;
3791 return "${var_run_tmpdir}/$vmid.vnc";
3792}
3793
943340a6 3794sub spice_port {
1011b570 3795 my ($vmid) = @_;
943340a6 3796
1d794448 3797 my $res = vm_mon_cmd($vmid, 'query-spice');
943340a6
DM
3798
3799 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
3800}
3801
c971c4f2 3802sub qmp_socket {
71bd73b5 3803 my ($vmid, $qga, $name) = @_;
693d12a2 3804 my $sockettype = $qga ? 'qga' : 'qmp';
71bd73b5
DC
3805 my $ext = $name ? '-'.$name : '';
3806 return "${var_run_tmpdir}/$vmid$ext.$sockettype";
c971c4f2
AD
3807}
3808
1e3baf05
DM
3809sub pidfile_name {
3810 my ($vmid) = @_;
3811 return "${var_run_tmpdir}/$vmid.pid";
3812}
3813
86fdcfb2
DA
3814sub vm_devices_list {
3815 my ($vmid) = @_;
3816
ceea9078 3817 my $res = vm_mon_cmd($vmid, 'query-pci');
f721624b 3818 my $devices_to_check = [];
ceea9078
DM
3819 my $devices = {};
3820 foreach my $pcibus (@$res) {
f721624b
DC
3821 push @$devices_to_check, @{$pcibus->{devices}},
3822 }
3823
3824 while (@$devices_to_check) {
3825 my $to_check = [];
3826 for my $d (@$devices_to_check) {
3827 $devices->{$d->{'qdev_id'}} = 1 if $d->{'qdev_id'};
3828 next if !$d->{'pci_bridge'};
3829
3830 $devices->{$d->{'qdev_id'}} += scalar(@{$d->{'pci_bridge'}->{devices}});
3831 push @$to_check, @{$d->{'pci_bridge'}->{devices}};
f78cc802 3832 }
f721624b 3833 $devices_to_check = $to_check;
f78cc802
AD
3834 }
3835
3836 my $resblock = vm_mon_cmd($vmid, 'query-block');
3837 foreach my $block (@$resblock) {
3838 if($block->{device} =~ m/^drive-(\S+)/){
3839 $devices->{$1} = 1;
1dc4f496
DM
3840 }
3841 }
86fdcfb2 3842
3d7389fe
DM
3843 my $resmice = vm_mon_cmd($vmid, 'query-mice');
3844 foreach my $mice (@$resmice) {
3845 if ($mice->{name} eq 'QEMU HID Tablet') {
3846 $devices->{tablet} = 1;
3847 last;
3848 }
3849 }
3850
deb091c5
DC
3851 # for usb devices there is no query-usb
3852 # but we can iterate over the entries in
3853 # qom-list path=/machine/peripheral
3854 my $resperipheral = vm_mon_cmd($vmid, 'qom-list', path => '/machine/peripheral');
3855 foreach my $per (@$resperipheral) {
3856 if ($per->{name} =~ m/^usb\d+$/) {
3857 $devices->{$per->{name}} = 1;
3858 }
3859 }
3860
1dc4f496 3861 return $devices;
86fdcfb2
DA
3862}
3863
ec21aa11 3864sub vm_deviceplug {
f19d1c47 3865 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 3866
db656e5f
DM
3867 my $q35 = machine_type_is_q35($conf);
3868
95d6343b
DA
3869 my $devices_list = vm_devices_list($vmid);
3870 return 1 if defined($devices_list->{$deviceid});
3871
fee46675
DM
3872 qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3873
3d7389fe 3874 if ($deviceid eq 'tablet') {
fee46675 3875
3d7389fe 3876 qemu_deviceadd($vmid, print_tabletdevice_full($conf));
3d7389fe 3877
4eb68604
DC
3878 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3879
f745762b
DC
3880 die "usb hotplug currently not reliable\n";
3881 # since we can't reliably hot unplug all added usb devices
3882 # and usb passthrough disables live migration
3883 # we disable usb hotplugging for now
4eb68604
DC
3884 qemu_deviceadd($vmid, PVE::QemuServer::USB::print_usbdevice_full($conf, $deviceid, $device));
3885
fee46675 3886 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
40f28a9f 3887
22de899a
AD
3888 qemu_iothread_add($vmid, $deviceid, $device);
3889
fee46675 3890 qemu_driveadd($storecfg, $vmid, $device);
cdd20088 3891 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
fee46675 3892
5e5dcb73 3893 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3894 eval { qemu_deviceaddverify($vmid, $deviceid); };
3895 if (my $err = $@) {
63c2da2f
DM
3896 eval { qemu_drivedel($vmid, $deviceid); };
3897 warn $@ if $@;
fee46675 3898 die $err;
5e5dcb73 3899 }
cfc817c7 3900
2733141c 3901 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
fee46675 3902
fc8b40fd 3903
cdd20088 3904 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
cfc817c7 3905 my $pciaddr = print_pci_addr($deviceid);
a1b7d579 3906 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
2733141c
AD
3907
3908 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
fee46675 3909
fc8b40fd
AD
3910 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
3911 qemu_iothread_add($vmid, $deviceid, $device);
3912 $devicefull .= ",iothread=iothread-$deviceid";
3913 }
3914
6e11f143
AD
3915 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues}) {
3916 $devicefull .= ",num_queues=$device->{queues}";
3917 }
3918
cfc817c7 3919 qemu_deviceadd($vmid, $devicefull);
fee46675 3920 qemu_deviceaddverify($vmid, $deviceid);
cfc817c7 3921
fee46675
DM
3922 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3923
3924 qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
3925 qemu_driveadd($storecfg, $vmid, $device);
a1b7d579 3926
fee46675
DM
3927 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
3928 eval { qemu_deviceadd($vmid, $devicefull); };
3929 if (my $err = $@) {
63c2da2f
DM
3930 eval { qemu_drivedel($vmid, $deviceid); };
3931 warn $@ if $@;
fee46675 3932 die $err;
a4f091a0 3933 }
a4f091a0 3934
fee46675
DM
3935 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3936
2630d2a9 3937 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
8718099c
AD
3938
3939 my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
3940 my $use_old_bios_files = undef;
3941 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
3942
3943 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
2630d2a9 3944 qemu_deviceadd($vmid, $netdevicefull);
fee46675
DM
3945 eval { qemu_deviceaddverify($vmid, $deviceid); };
3946 if (my $err = $@) {
3947 eval { qemu_netdevdel($vmid, $deviceid); };
3948 warn $@ if $@;
3949 die $err;
2630d2a9 3950 }
2630d2a9 3951
fee46675 3952 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
b467f79a 3953
40f28a9f
AD
3954 my $bridgeid = $2;
3955 my $pciaddr = print_pci_addr($deviceid);
3956 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
a1b7d579 3957
40f28a9f 3958 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3959 qemu_deviceaddverify($vmid, $deviceid);
3960
3961 } else {
a1b7d579 3962 die "can't hotplug device '$deviceid'\n";
40f28a9f
AD
3963 }
3964
5e5dcb73 3965 return 1;
a4dea331
DA
3966}
3967
3eec5767 3968# fixme: this should raise exceptions on error!
ec21aa11 3969sub vm_deviceunplug {
f19d1c47 3970 my ($vmid, $conf, $deviceid) = @_;
873c2d69 3971
95d6343b
DA
3972 my $devices_list = vm_devices_list($vmid);
3973 return 1 if !defined($devices_list->{$deviceid});
3974
63c2da2f
DM
3975 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
3976
3d7389fe 3977 if ($deviceid eq 'tablet') {
63c2da2f 3978
3d7389fe 3979 qemu_devicedel($vmid, $deviceid);
3d7389fe 3980
4eb68604
DC
3981 } elsif ($deviceid =~ m/^usb\d+$/) {
3982
f745762b
DC
3983 die "usb hotplug currently not reliable\n";
3984 # when unplugging usb devices this way,
3985 # there may be remaining usb controllers/hubs
3986 # so we disable it for now
4eb68604
DC
3987 qemu_devicedel($vmid, $deviceid);
3988 qemu_devicedelverify($vmid, $deviceid);
3989
63c2da2f 3990 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
f19d1c47 3991
5e5dcb73 3992 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
3993 qemu_devicedelverify($vmid, $deviceid);
3994 qemu_drivedel($vmid, $deviceid);
22de899a
AD
3995 qemu_iothread_del($conf, $vmid, $deviceid);
3996
2733141c 3997 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
a1b7d579 3998
63c2da2f 3999 qemu_devicedel($vmid, $deviceid);
8ce30dde 4000 qemu_devicedelverify($vmid, $deviceid);
fc8b40fd 4001 qemu_iothread_del($conf, $vmid, $deviceid);
a1b7d579 4002
63c2da2f 4003 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
cfc817c7 4004
63c2da2f
DM
4005 qemu_devicedel($vmid, $deviceid);
4006 qemu_drivedel($vmid, $deviceid);
a1b7d579 4007 qemu_deletescsihw($conf, $vmid, $deviceid);
8ce30dde 4008
63c2da2f 4009 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
a4f091a0 4010
2630d2a9 4011 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
4012 qemu_devicedelverify($vmid, $deviceid);
4013 qemu_netdevdel($vmid, $deviceid);
4014
4015 } else {
4016 die "can't unplug device '$deviceid'\n";
2630d2a9
DA
4017 }
4018
5e5dcb73
DA
4019 return 1;
4020}
4021
4022sub qemu_deviceadd {
4023 my ($vmid, $devicefull) = @_;
873c2d69 4024
d695b5b7
AD
4025 $devicefull = "driver=".$devicefull;
4026 my %options = split(/[=,]/, $devicefull);
f19d1c47 4027
d695b5b7 4028 vm_mon_cmd($vmid, "device_add" , %options);
5e5dcb73 4029}
afdb31d5 4030
5e5dcb73 4031sub qemu_devicedel {
fee46675 4032 my ($vmid, $deviceid) = @_;
63c2da2f 4033
5a77d8c1 4034 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
5e5dcb73
DA
4035}
4036
22de899a
AD
4037sub qemu_iothread_add {
4038 my($vmid, $deviceid, $device) = @_;
4039
4040 if ($device->{iothread}) {
4041 my $iothreads = vm_iothreads_list($vmid);
4042 qemu_objectadd($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
4043 }
4044}
4045
4046sub qemu_iothread_del {
4047 my($conf, $vmid, $deviceid) = @_;
4048
4049 my $device = parse_drive($deviceid, $conf->{$deviceid});
4050 if ($device->{iothread}) {
4051 my $iothreads = vm_iothreads_list($vmid);
4052 qemu_objectdel($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
4053 }
4054}
4055
4d3f29ed
AD
4056sub qemu_objectadd {
4057 my($vmid, $objectid, $qomtype) = @_;
4058
4059 vm_mon_cmd($vmid, "object-add", id => $objectid, "qom-type" => $qomtype);
4060
4061 return 1;
4062}
4063
4064sub qemu_objectdel {
4065 my($vmid, $objectid) = @_;
4066
4067 vm_mon_cmd($vmid, "object-del", id => $objectid);
4068
4069 return 1;
4070}
4071
5e5dcb73 4072sub qemu_driveadd {
fee46675 4073 my ($storecfg, $vmid, $device) = @_;
5e5dcb73
DA
4074
4075 my $drive = print_drive_full($storecfg, $vmid, $device);
7a69fc3c 4076 $drive =~ s/\\/\\\\/g;
8ead5ec7 4077 my $ret = vm_human_monitor_command($vmid, "drive_add auto \"$drive\"");
fee46675 4078
5e5dcb73 4079 # If the command succeeds qemu prints: "OK"
fee46675
DM
4080 return 1 if $ret =~ m/OK/s;
4081
4082 die "adding drive failed: $ret\n";
5e5dcb73 4083}
afdb31d5 4084
5e5dcb73
DA
4085sub qemu_drivedel {
4086 my($vmid, $deviceid) = @_;
873c2d69 4087
7b7c6d1b 4088 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73 4089 $ret =~ s/^\s+//;
a1b7d579 4090
63c2da2f 4091 return 1 if $ret eq "";
a1b7d579 4092
63c2da2f 4093 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
a1b7d579
DM
4094 return 1 if $ret =~ m/Device \'.*?\' not found/s;
4095
63c2da2f 4096 die "deleting drive $deviceid failed : $ret\n";
5e5dcb73 4097}
f19d1c47 4098
5e5dcb73 4099sub qemu_deviceaddverify {
fee46675 4100 my ($vmid, $deviceid) = @_;
873c2d69 4101
5e5dcb73
DA
4102 for (my $i = 0; $i <= 5; $i++) {
4103 my $devices_list = vm_devices_list($vmid);
4104 return 1 if defined($devices_list->{$deviceid});
4105 sleep 1;
afdb31d5 4106 }
fee46675
DM
4107
4108 die "error on hotplug device '$deviceid'\n";
5e5dcb73 4109}
afdb31d5 4110
5e5dcb73
DA
4111
4112sub qemu_devicedelverify {
63c2da2f
DM
4113 my ($vmid, $deviceid) = @_;
4114
a1b7d579 4115 # need to verify that the device is correctly removed as device_del
63c2da2f 4116 # is async and empty return is not reliable
5e5dcb73 4117
5e5dcb73
DA
4118 for (my $i = 0; $i <= 5; $i++) {
4119 my $devices_list = vm_devices_list($vmid);
4120 return 1 if !defined($devices_list->{$deviceid});
4121 sleep 1;
afdb31d5 4122 }
63c2da2f
DM
4123
4124 die "error on hot-unplugging device '$deviceid'\n";
873c2d69
DA
4125}
4126
cdd20088 4127sub qemu_findorcreatescsihw {
cfc817c7
DA
4128 my ($storecfg, $conf, $vmid, $device) = @_;
4129
ee034f5c 4130 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
2733141c
AD
4131
4132 my $scsihwid="$controller_prefix$controller";
cfc817c7
DA
4133 my $devices_list = vm_devices_list($vmid);
4134
cdd20088 4135 if(!defined($devices_list->{$scsihwid})) {
fc8b40fd 4136 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
cfc817c7 4137 }
fee46675 4138
cfc817c7
DA
4139 return 1;
4140}
4141
8ce30dde
AD
4142sub qemu_deletescsihw {
4143 my ($conf, $vmid, $opt) = @_;
4144
4145 my $device = parse_drive($opt, $conf->{$opt});
4146
a1511b3c 4147 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
2733141c
AD
4148 vm_deviceunplug($vmid, $conf, "virtioscsi$device->{index}");
4149 return 1;
4150 }
4151
ee034f5c 4152 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
8ce30dde
AD
4153
4154 my $devices_list = vm_devices_list($vmid);
4155 foreach my $opt (keys %{$devices_list}) {
74479ee9 4156 if (PVE::QemuServer::is_valid_drivename($opt)) {
8ce30dde
AD
4157 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
4158 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
4159 return 1;
4160 }
4161 }
4162 }
4163
4164 my $scsihwid="scsihw$controller";
4165
4166 vm_deviceunplug($vmid, $conf, $scsihwid);
4167
4168 return 1;
4169}
4170
281fedb3 4171sub qemu_add_pci_bridge {
40f28a9f
AD
4172 my ($storecfg, $conf, $vmid, $device) = @_;
4173
4174 my $bridges = {};
281fedb3
DM
4175
4176 my $bridgeid;
4177
40f28a9f
AD
4178 print_pci_addr($device, $bridges);
4179
4180 while (my ($k, $v) = each %$bridges) {
4181 $bridgeid = $k;
4182 }
fee46675 4183 return 1 if !defined($bridgeid) || $bridgeid < 1;
281fedb3 4184
40f28a9f
AD
4185 my $bridge = "pci.$bridgeid";
4186 my $devices_list = vm_devices_list($vmid);
4187
281fedb3 4188 if (!defined($devices_list->{$bridge})) {
fee46675 4189 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
40f28a9f 4190 }
281fedb3 4191
40f28a9f
AD
4192 return 1;
4193}
4194
25088687
DM
4195sub qemu_set_link_status {
4196 my ($vmid, $device, $up) = @_;
4197
a1b7d579 4198 vm_mon_cmd($vmid, "set_link", name => $device,
25088687
DM
4199 up => $up ? JSON::true : JSON::false);
4200}
4201
2630d2a9
DA
4202sub qemu_netdevadd {
4203 my ($vmid, $conf, $device, $deviceid) = @_;
4204
208ba94e 4205 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
73aa03b8 4206 my %options = split(/[=,]/, $netdev);
2630d2a9 4207
73aa03b8
AD
4208 vm_mon_cmd($vmid, "netdev_add", %options);
4209 return 1;
2630d2a9
DA
4210}
4211
4212sub qemu_netdevdel {
4213 my ($vmid, $deviceid) = @_;
4214
89c1e0f4 4215 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2630d2a9
DA
4216}
4217
16521d63
DC
4218sub qemu_usb_hotplug {
4219 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
4220
4221 return if !$device;
4222
4223 # remove the old one first
4224 vm_deviceunplug($vmid, $conf, $deviceid);
4225
4226 # check if xhci controller is necessary and available
4227 if ($device->{usb3}) {
4228
4229 my $devicelist = vm_devices_list($vmid);
4230
4231 if (!$devicelist->{xhci}) {
4232 my $pciaddr = print_pci_addr("xhci");
4233 qemu_deviceadd($vmid, "nec-usb-xhci,id=xhci$pciaddr");
4234 }
4235 }
4236 my $d = parse_usb_device($device->{host});
4237 $d->{usb3} = $device->{usb3};
4238
4239 # add the new one
4240 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
4241}
4242
838776ab 4243sub qemu_cpu_hotplug {
8edc9c08 4244 my ($vmid, $conf, $vcpus) = @_;
838776ab 4245
1e881b75
AD
4246 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
4247
8edc9c08
AD
4248 my $sockets = 1;
4249 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
4250 $sockets = $conf->{sockets} if $conf->{sockets};
4251 my $cores = $conf->{cores} || 1;
4252 my $maxcpus = $sockets * $cores;
838776ab 4253
8edc9c08 4254 $vcpus = $maxcpus if !$vcpus;
3a11fadb 4255
8edc9c08
AD
4256 die "you can't add more vcpus than maxcpus\n"
4257 if $vcpus > $maxcpus;
3a11fadb 4258
8edc9c08 4259 my $currentvcpus = $conf->{vcpus} || $maxcpus;
1e881b75 4260
eba3e64d 4261 if ($vcpus < $currentvcpus) {
1e881b75
AD
4262
4263 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4264
4265 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
4266 qemu_devicedel($vmid, "cpu$i");
4267 my $retry = 0;
4268 my $currentrunningvcpus = undef;
4269 while (1) {
4270 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4271 last if scalar(@{$currentrunningvcpus}) == $i-1;
961af8a3 4272 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
1e881b75
AD
4273 $retry++;
4274 sleep 1;
4275 }
4276 #update conf after each succesfull cpu unplug
4277 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4278 PVE::QemuConfig->write_config($vmid, $conf);
4279 }
4280 } else {
961af8a3 4281 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
1e881b75
AD
4282 }
4283
4284 return;
4285 }
838776ab 4286
8edc9c08 4287 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
961af8a3 4288 die "vcpus in running vm does not match its configuration\n"
8edc9c08 4289 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
838776ab 4290
eba3e64d
AD
4291 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4292
4293 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
4294 my $cpustr = print_cpu_device($conf, $i);
4295 qemu_deviceadd($vmid, $cpustr);
4296
4297 my $retry = 0;
4298 my $currentrunningvcpus = undef;
4299 while (1) {
4300 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4301 last if scalar(@{$currentrunningvcpus}) == $i;
961af8a3 4302 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
eba3e64d
AD
4303 sleep 1;
4304 $retry++;
4305 }
4306 #update conf after each succesfull cpu hotplug
4307 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4308 PVE::QemuConfig->write_config($vmid, $conf);
4309 }
4310 } else {
4311
4312 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
4313 vm_mon_cmd($vmid, "cpu-add", id => int($i));
4314 }
838776ab
AD
4315 }
4316}
4317
affd2f88 4318sub qemu_block_set_io_throttle {
277ca170
WB
4319 my ($vmid, $deviceid,
4320 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
9196a8ec
WB
4321 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
4322 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
4323 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
affd2f88 4324
f3f323a3
AD
4325 return if !check_running($vmid) ;
4326
277ca170
WB
4327 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
4328 bps => int($bps),
4329 bps_rd => int($bps_rd),
4330 bps_wr => int($bps_wr),
4331 iops => int($iops),
4332 iops_rd => int($iops_rd),
4333 iops_wr => int($iops_wr),
4334 bps_max => int($bps_max),
4335 bps_rd_max => int($bps_rd_max),
4336 bps_wr_max => int($bps_wr_max),
4337 iops_max => int($iops_max),
4338 iops_rd_max => int($iops_rd_max),
9196a8ec
WB
4339 iops_wr_max => int($iops_wr_max),
4340 bps_max_length => int($bps_max_length),
4341 bps_rd_max_length => int($bps_rd_max_length),
4342 bps_wr_max_length => int($bps_wr_max_length),
4343 iops_max_length => int($iops_max_length),
4344 iops_rd_max_length => int($iops_rd_max_length),
4345 iops_wr_max_length => int($iops_wr_max_length),
277ca170 4346 );
f3f323a3 4347
affd2f88
AD
4348}
4349
f5eb281a 4350# old code, only used to shutdown old VM after update
dab36e1e
DM
4351sub __read_avail {
4352 my ($fh, $timeout) = @_;
4353
4354 my $sel = new IO::Select;
4355 $sel->add($fh);
4356
4357 my $res = '';
4358 my $buf;
4359
4360 my @ready;
4361 while (scalar (@ready = $sel->can_read($timeout))) {
4362 my $count;
4363 if ($count = $fh->sysread($buf, 8192)) {
4364 if ($buf =~ /^(.*)\(qemu\) $/s) {
4365 $res .= $1;
4366 last;
4367 } else {
4368 $res .= $buf;
4369 }
4370 } else {
4371 if (!defined($count)) {
4372 die "$!\n";
4373 }
4374 last;
4375 }
4376 }
4377
4378 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 4379
dab36e1e
DM
4380 return $res;
4381}
4382
c1175c92
AD
4383sub qemu_block_resize {
4384 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4385
ed221350 4386 my $running = check_running($vmid);
c1175c92 4387
7246e8f9 4388 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
c1175c92
AD
4389
4390 return if !$running;
4391
4392 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4393
4394}
4395
1ab0057c
AD
4396sub qemu_volume_snapshot {
4397 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4398
ed221350 4399 my $running = check_running($vmid);
1ab0057c 4400
e5eaa028 4401 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
eba2b721 4402 vm_mon_cmd($vmid, 'blockdev-snapshot-internal-sync', device => $deviceid, name => $snap);
e5eaa028
WL
4403 } else {
4404 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4405 }
1ab0057c
AD
4406}
4407
fc46aff9
AD
4408sub qemu_volume_snapshot_delete {
4409 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4410
ed221350 4411 my $running = check_running($vmid);
fc46aff9 4412
a2f1554b
AD
4413 if($running) {
4414
4415 $running = undef;
4416 my $conf = PVE::QemuConfig->load_config($vmid);
4417 foreach_drive($conf, sub {
4418 my ($ds, $drive) = @_;
4419 $running = 1 if $drive->{file} eq $volid;
4420 });
4421 }
4422
1ef7592f 4423 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
eba2b721 4424 vm_mon_cmd($vmid, 'blockdev-snapshot-delete-internal-sync', device => $deviceid, name => $snap);
1ef7592f
AD
4425 } else {
4426 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4427 }
fc46aff9
AD
4428}
4429
264e519f
DM
4430sub set_migration_caps {
4431 my ($vmid) = @_;
a89fded1 4432
8b8345f3 4433 my $cap_ref = [];
a89fded1
AD
4434
4435 my $enabled_cap = {
8b8345f3 4436 "auto-converge" => 1,
0b0a47e8 4437 "xbzrle" => 1,
8b8345f3
DM
4438 "x-rdma-pin-all" => 0,
4439 "zero-blocks" => 0,
b62532e4 4440 "compress" => 0
a89fded1
AD
4441 };
4442
8b8345f3 4443 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
a89fded1 4444
8b8345f3 4445 for my $supported_capability (@$supported_capabilities) {
b463a3ce
SP
4446 push @$cap_ref, {
4447 capability => $supported_capability->{capability},
22430fa2
DM
4448 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4449 };
a89fded1
AD
4450 }
4451
8b8345f3
DM
4452 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4453}
a89fded1 4454
81d95ae1 4455my $fast_plug_option = {
7498eb64 4456 'lock' => 1,
81d95ae1 4457 'name' => 1,
a1b7d579 4458 'onboot' => 1,
81d95ae1
DM
4459 'shares' => 1,
4460 'startup' => 1,
b0ec896e 4461 'description' => 1,
ec647db4 4462 'protection' => 1,
8cad5e9b 4463 'vmstatestorage' => 1,
81d95ae1
DM
4464};
4465
3a11fadb
DM
4466# hotplug changes in [PENDING]
4467# $selection hash can be used to only apply specified options, for
4468# example: { cores => 1 } (only apply changed 'cores')
4469# $errors ref is used to return error messages
c427973b 4470sub vmconfig_hotplug_pending {
3a11fadb 4471 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
c427973b 4472
8e90138a 4473 my $defaults = load_defaults();
c427973b
DM
4474
4475 # commit values which do not have any impact on running VM first
3a11fadb
DM
4476 # Note: those option cannot raise errors, we we do not care about
4477 # $selection and always apply them.
4478
4479 my $add_error = sub {
4480 my ($opt, $msg) = @_;
4481 $errors->{$opt} = "hotplug problem - $msg";
4482 };
c427973b
DM
4483
4484 my $changes = 0;
4485 foreach my $opt (keys %{$conf->{pending}}) { # add/change
81d95ae1 4486 if ($fast_plug_option->{$opt}) {
c427973b
DM
4487 $conf->{$opt} = $conf->{pending}->{$opt};
4488 delete $conf->{pending}->{$opt};
4489 $changes = 1;
4490 }
4491 }
4492
4493 if ($changes) {
ffda963f
FG
4494 PVE::QemuConfig->write_config($vmid, $conf);
4495 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
c427973b
DM
4496 }
4497
b3c2bdd1 4498 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
c427973b 4499
3dc38fbb
WB
4500 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4501 while (my ($opt, $force) = each %$pending_delete_hash) {
3a11fadb 4502 next if $selection && !$selection->{$opt};
3a11fadb 4503 eval {
51a6f637
AD
4504 if ($opt eq 'hotplug') {
4505 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4506 } elsif ($opt eq 'tablet') {
b3c2bdd1 4507 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4508 if ($defaults->{tablet}) {
4509 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4510 } else {
4511 vm_deviceunplug($vmid, $conf, $opt);
4512 }
4eb68604 4513 } elsif ($opt =~ m/^usb\d+/) {
f745762b
DC
4514 die "skip\n";
4515 # since we cannot reliably hot unplug usb devices
4516 # we are disabling it
4eb68604
DC
4517 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4518 vm_deviceunplug($vmid, $conf, $opt);
8edc9c08 4519 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4520 die "skip\n" if !$hotplug_features->{cpu};
8edc9c08 4521 qemu_cpu_hotplug($vmid, $conf, undef);
9c2f7069 4522 } elsif ($opt eq 'balloon') {
81d95ae1 4523 # enable balloon device is not hotpluggable
75b51053
DC
4524 die "skip\n" if defined($conf->{balloon}) && $conf->{balloon} == 0;
4525 # here we reset the ballooning value to memory
4526 my $balloon = $conf->{memory} || $defaults->{memory};
4527 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
81d95ae1
DM
4528 } elsif ($fast_plug_option->{$opt}) {
4529 # do nothing
3eec5767 4530 } elsif ($opt =~ m/^net(\d+)$/) {
b3c2bdd1 4531 die "skip\n" if !$hotplug_features->{network};
3eec5767 4532 vm_deviceunplug($vmid, $conf, $opt);
74479ee9 4533 } elsif (is_valid_drivename($opt)) {
b3c2bdd1 4534 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
19120f99 4535 vm_deviceunplug($vmid, $conf, $opt);
3dc38fbb 4536 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4d3f29ed
AD
4537 } elsif ($opt =~ m/^memory$/) {
4538 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4539 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
c8effec3
AD
4540 } elsif ($opt eq 'cpuunits') {
4541 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
58be00f1
AD
4542 } elsif ($opt eq 'cpulimit') {
4543 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3d7389fe 4544 } else {
e56beeda 4545 die "skip\n";
3d7389fe 4546 }
3a11fadb
DM
4547 };
4548 if (my $err = $@) {
e56beeda
DM
4549 &$add_error($opt, $err) if $err ne "skip\n";
4550 } else {
3a11fadb
DM
4551 # save new config if hotplug was successful
4552 delete $conf->{$opt};
4553 vmconfig_undelete_pending_option($conf, $opt);
ffda963f
FG
4554 PVE::QemuConfig->write_config($vmid, $conf);
4555 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4556 }
3d7389fe
DM
4557 }
4558
9ed7a77c
WB
4559 my $apply_pending_cloudinit;
4560 $apply_pending_cloudinit = sub {
4561 my ($key, $value) = @_;
4562 $apply_pending_cloudinit = sub {}; # once is enough
4563
4564 my @cloudinit_opts = keys %$confdesc_cloudinit;
4565 foreach my $opt (keys %{$conf->{pending}}) {
4566 next if !grep { $_ eq $opt } @cloudinit_opts;
4567 $conf->{$opt} = delete $conf->{pending}->{$opt};
4568 }
4569
4570 my $new_conf = { %$conf };
4571 $new_conf->{$key} = $value;
4572 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($new_conf, $vmid);
4573 };
4574
3d7389fe 4575 foreach my $opt (keys %{$conf->{pending}}) {
3a11fadb 4576 next if $selection && !$selection->{$opt};
3d7389fe 4577 my $value = $conf->{pending}->{$opt};
3a11fadb 4578 eval {
51a6f637
AD
4579 if ($opt eq 'hotplug') {
4580 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4581 } elsif ($opt eq 'tablet') {
b3c2bdd1 4582 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4583 if ($value == 1) {
4584 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4585 } elsif ($value == 0) {
4586 vm_deviceunplug($vmid, $conf, $opt);
4587 }
4eb68604 4588 } elsif ($opt =~ m/^usb\d+$/) {
f745762b
DC
4589 die "skip\n";
4590 # since we cannot reliably hot unplug usb devices
4591 # we are disabling it
4eb68604
DC
4592 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4593 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4594 die "skip\n" if !$d;
4595 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
8edc9c08 4596 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4597 die "skip\n" if !$hotplug_features->{cpu};
3a11fadb
DM
4598 qemu_cpu_hotplug($vmid, $conf, $value);
4599 } elsif ($opt eq 'balloon') {
81d95ae1 4600 # enable/disable balloning device is not hotpluggable
8fe689e7 4601 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
a1b7d579 4602 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
81d95ae1
DM
4603 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4604
3a11fadb 4605 # allow manual ballooning if shares is set to zero
4cc1efa6 4606 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
9c2f7069
AD
4607 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4608 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4609 }
a1b7d579 4610 } elsif ($opt =~ m/^net(\d+)$/) {
3eec5767 4611 # some changes can be done without hotplug
a1b7d579 4612 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
b3c2bdd1 4613 $vmid, $opt, $value);
74479ee9 4614 } elsif (is_valid_drivename($opt)) {
a05cff86 4615 # some changes can be done without hotplug
9ed7a77c
WB
4616 my $drive = parse_drive($opt, $value);
4617 if (drive_is_cloudinit($drive)) {
4618 &$apply_pending_cloudinit($opt, $value);
4619 }
b3c2bdd1
DM
4620 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4621 $vmid, $opt, $value, 1);
4d3f29ed
AD
4622 } elsif ($opt =~ m/^memory$/) { #dimms
4623 die "skip\n" if !$hotplug_features->{memory};
6779f1ac 4624 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
c8effec3
AD
4625 } elsif ($opt eq 'cpuunits') {
4626 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
58be00f1 4627 } elsif ($opt eq 'cpulimit') {
c6f773b8 4628 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
58be00f1 4629 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
3a11fadb 4630 } else {
e56beeda 4631 die "skip\n"; # skip non-hot-pluggable options
3d7389fe 4632 }
3a11fadb
DM
4633 };
4634 if (my $err = $@) {
e56beeda
DM
4635 &$add_error($opt, $err) if $err ne "skip\n";
4636 } else {
3a11fadb
DM
4637 # save new config if hotplug was successful
4638 $conf->{$opt} = $value;
4639 delete $conf->{pending}->{$opt};
ffda963f
FG
4640 PVE::QemuConfig->write_config($vmid, $conf);
4641 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4642 }
3d7389fe 4643 }
c427973b 4644}
055d554d 4645
3dc38fbb
WB
4646sub try_deallocate_drive {
4647 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4648
4649 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4650 my $volid = $drive->{file};
4651 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4652 my $sid = PVE::Storage::parse_volume_id($volid);
4653 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
cee01bcb
WB
4654
4655 # check if the disk is really unused
cee01bcb 4656 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
77019edf 4657 if is_volume_in_use($storecfg, $conf, $key, $volid);
cee01bcb 4658 PVE::Storage::vdisk_free($storecfg, $volid);
3dc38fbb 4659 return 1;
40b977f3
WL
4660 } else {
4661 # If vm is not owner of this disk remove from config
4662 return 1;
3dc38fbb
WB
4663 }
4664 }
4665
4666 return undef;
4667}
4668
4669sub vmconfig_delete_or_detach_drive {
4670 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4671
4672 my $drive = parse_drive($opt, $conf->{$opt});
4673
4674 my $rpcenv = PVE::RPCEnvironment::get();
4675 my $authuser = $rpcenv->get_user();
4676
4677 if ($force) {
4678 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4679 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4680 } else {
4681 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4682 }
4683}
4684
055d554d 4685sub vmconfig_apply_pending {
3a11fadb 4686 my ($vmid, $conf, $storecfg) = @_;
c427973b
DM
4687
4688 # cold plug
055d554d 4689
3dc38fbb
WB
4690 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4691 while (my ($opt, $force) = each %$pending_delete_hash) {
055d554d 4692 die "internal error" if $opt =~ m/^unused/;
ffda963f 4693 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4694 if (!defined($conf->{$opt})) {
4695 vmconfig_undelete_pending_option($conf, $opt);
ffda963f 4696 PVE::QemuConfig->write_config($vmid, $conf);
74479ee9 4697 } elsif (is_valid_drivename($opt)) {
3dc38fbb 4698 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
055d554d
DM
4699 vmconfig_undelete_pending_option($conf, $opt);
4700 delete $conf->{$opt};
ffda963f 4701 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4702 } else {
4703 vmconfig_undelete_pending_option($conf, $opt);
4704 delete $conf->{$opt};
ffda963f 4705 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4706 }
4707 }
4708
ffda963f 4709 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4710
4711 foreach my $opt (keys %{$conf->{pending}}) { # add/change
ffda963f 4712 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4713
4714 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4715 # skip if nothing changed
74479ee9 4716 } elsif (is_valid_drivename($opt)) {
055d554d
DM
4717 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4718 if defined($conf->{$opt});
4719 $conf->{$opt} = $conf->{pending}->{$opt};
4720 } else {
4721 $conf->{$opt} = $conf->{pending}->{$opt};
4722 }
4723
4724 delete $conf->{pending}->{$opt};
ffda963f 4725 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4726 }
4727}
4728
3eec5767
DM
4729my $safe_num_ne = sub {
4730 my ($a, $b) = @_;
4731
4732 return 0 if !defined($a) && !defined($b);
4733 return 1 if !defined($a);
4734 return 1 if !defined($b);
4735
4736 return $a != $b;
4737};
4738
4739my $safe_string_ne = sub {
4740 my ($a, $b) = @_;
4741
4742 return 0 if !defined($a) && !defined($b);
4743 return 1 if !defined($a);
4744 return 1 if !defined($b);
4745
4746 return $a ne $b;
4747};
4748
4749sub vmconfig_update_net {
b3c2bdd1 4750 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
3eec5767
DM
4751
4752 my $newnet = parse_net($value);
4753
4754 if ($conf->{$opt}) {
4755 my $oldnet = parse_net($conf->{$opt});
4756
4757 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4758 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4759 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4760 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4761
4762 # for non online change, we try to hot-unplug
7196b757 4763 die "skip\n" if !$hotplug;
3eec5767
DM
4764 vm_deviceunplug($vmid, $conf, $opt);
4765 } else {
4766
4767 die "internal error" if $opt !~ m/net(\d+)/;
4768 my $iface = "tap${vmid}i$1";
a1b7d579 4769
25088687
DM
4770 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4771 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
16d08ecf 4772 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
25088687 4773 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
3eec5767 4774 PVE::Network::tap_unplug($iface);
4f4fbeb0
WB
4775 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4776 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4777 # Rate can be applied on its own but any change above needs to
4778 # include the rate in tap_plug since OVS resets everything.
4779 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
3eec5767 4780 }
38c590d9 4781
25088687
DM
4782 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4783 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4784 }
4785
38c590d9 4786 return 1;
3eec5767
DM
4787 }
4788 }
a1b7d579 4789
7196b757 4790 if ($hotplug) {
38c590d9
DM
4791 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4792 } else {
4793 die "skip\n";
4794 }
3eec5767
DM
4795}
4796
a05cff86 4797sub vmconfig_update_disk {
b3c2bdd1 4798 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
a05cff86
DM
4799
4800 # fixme: do we need force?
4801
4802 my $drive = parse_drive($opt, $value);
4803
4804 if ($conf->{$opt}) {
4805
4806 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4807
4808 my $media = $drive->{media} || 'disk';
4809 my $oldmedia = $old_drive->{media} || 'disk';
4810 die "unable to change media type\n" if $media ne $oldmedia;
4811
4812 if (!drive_is_cdrom($old_drive)) {
4813
a1b7d579 4814 if ($drive->{file} ne $old_drive->{file}) {
a05cff86 4815
7196b757 4816 die "skip\n" if !$hotplug;
a05cff86
DM
4817
4818 # unplug and register as unused
4819 vm_deviceunplug($vmid, $conf, $opt);
4820 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
a1b7d579 4821
a05cff86
DM
4822 } else {
4823 # update existing disk
4824
4825 # skip non hotpluggable value
6ecfbb44 4826 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
22de899a 4827 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
6e11f143 4828 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
a05cff86
DM
4829 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4830 die "skip\n";
4831 }
4832
4833 # apply throttle
4834 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4835 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4836 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4837 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4838 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4839 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4840 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4841 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4842 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4843 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4844 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
9196a8ec
WB
4845 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4846 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4847 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4848 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4849 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4850 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4851 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
a1b7d579 4852
a05cff86
DM
4853 qemu_block_set_io_throttle($vmid,"drive-$opt",
4854 ($drive->{mbps} || 0)*1024*1024,
4855 ($drive->{mbps_rd} || 0)*1024*1024,
4856 ($drive->{mbps_wr} || 0)*1024*1024,
4857 $drive->{iops} || 0,
4858 $drive->{iops_rd} || 0,
4859 $drive->{iops_wr} || 0,
4860 ($drive->{mbps_max} || 0)*1024*1024,
4861 ($drive->{mbps_rd_max} || 0)*1024*1024,
4862 ($drive->{mbps_wr_max} || 0)*1024*1024,
4863 $drive->{iops_max} || 0,
4864 $drive->{iops_rd_max} || 0,
9196a8ec
WB
4865 $drive->{iops_wr_max} || 0,
4866 $drive->{bps_max_length} || 1,
4867 $drive->{bps_rd_max_length} || 1,
4868 $drive->{bps_wr_max_length} || 1,
4869 $drive->{iops_max_length} || 1,
4870 $drive->{iops_rd_max_length} || 1,
4871 $drive->{iops_wr_max_length} || 1);
a05cff86
DM
4872
4873 }
a1b7d579 4874
a05cff86
DM
4875 return 1;
4876 }
4de1bb25
DM
4877
4878 } else { # cdrom
a1b7d579 4879
4de1bb25
DM
4880 if ($drive->{file} eq 'none') {
4881 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
2d9ddec5
WB
4882 if (drive_is_cloudinit($old_drive)) {
4883 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive);
4884 }
4de1bb25
DM
4885 } else {
4886 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4887 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4888 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4889 }
a1b7d579 4890
34758d66 4891 return 1;
a05cff86
DM
4892 }
4893 }
4894 }
4895
a1b7d579 4896 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4de1bb25 4897 # hotplug new disks
f7b4356f 4898 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4de1bb25 4899 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
a05cff86
DM
4900}
4901
1e3baf05 4902sub vm_start {
ba9e1000 4903 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
2189246c 4904 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
1e3baf05 4905
ffda963f
FG
4906 PVE::QemuConfig->lock_config($vmid, sub {
4907 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
1e3baf05 4908
ffda963f 4909 die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
3dcb98d5 4910
ffda963f 4911 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4912
7e8dcf2c 4913 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 4914
055d554d 4915 if (!$statefile && scalar(keys %{$conf->{pending}})) {
3a11fadb 4916 vmconfig_apply_pending($vmid, $conf, $storecfg);
ffda963f 4917 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4918 }
4919
0c9a7596
AD
4920 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
4921
6c47d546
DM
4922 my $defaults = load_defaults();
4923
4924 # set environment variable useful inside network script
4925 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4926
2189246c
AD
4927 my $local_volumes = {};
4928
3b4cf0f0 4929 if ($targetstorage) {
2189246c
AD
4930 foreach_drive($conf, sub {
4931 my ($ds, $drive) = @_;
4932
4933 return if drive_is_cdrom($drive);
4934
4935 my $volid = $drive->{file};
4936
4937 return if !$volid;
4938
4939 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4940
4941 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4942 return if $scfg->{shared};
4943 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4944 });
4945
4946 my $format = undef;
4947
4948 foreach my $opt (sort keys %$local_volumes) {
4949
4950 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4951 my $drive = parse_drive($opt, $conf->{$opt});
4952
4953 #if remote storage is specified, use default format
4954 if ($targetstorage && $targetstorage ne "1") {
4955 $storeid = $targetstorage;
4956 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4957 $format = $defFormat;
4958 } else {
4959 #else we use same format than original
4960 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4961 $format = qemu_img_format($scfg, $volid);
4962 }
4963
4964 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4965 my $newdrive = $drive;
4966 $newdrive->{format} = $format;
4967 $newdrive->{file} = $newvolid;
4968 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4969 $local_volumes->{$opt} = $drivestr;
4970 #pass drive to conf for command line
4971 $conf->{$opt} = $drivestr;
4972 }
4973 }
4974
67812f9c 4975 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 4976
1e3baf05 4977 my $migrate_port = 0;
5bc1e039 4978 my $migrate_uri;
1e3baf05
DM
4979 if ($statefile) {
4980 if ($statefile eq 'tcp') {
5bc1e039
SP
4981 my $localip = "localhost";
4982 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
af0eba7e 4983 my $nodename = PVE::INotify::nodename();
2de2d6f7 4984
b7a5a225
TL
4985 if (!defined($migration_type)) {
4986 if (defined($datacenterconf->{migration}->{type})) {
4987 $migration_type = $datacenterconf->{migration}->{type};
4988 } else {
4989 $migration_type = 'secure';
4990 }
4991 }
4992
2de2d6f7
TL
4993 if ($migration_type eq 'insecure') {
4994 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4995 if ($migrate_network_addr) {
4996 $localip = $migrate_network_addr;
4997 } else {
5bc1e039 4998 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
2de2d6f7
TL
4999 }
5000
5001 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5bc1e039 5002 }
2de2d6f7 5003
af0eba7e
WB
5004 my $pfamily = PVE::Tools::get_host_address_family($nodename);
5005 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
407e0b8b 5006 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
5007 push @$cmd, '-incoming', $migrate_uri;
5008 push @$cmd, '-S';
1c9d54bf
TL
5009
5010 } elsif ($statefile eq 'unix') {
5011 # should be default for secure migrations as a ssh TCP forward
5012 # tunnel is not deterministic reliable ready and fails regurarly
5013 # to set up in time, so use UNIX socket forwards
54323eed
TL
5014 my $socket_addr = "/run/qemu-server/$vmid.migrate";
5015 unlink $socket_addr;
5016
5017 $migrate_uri = "unix:$socket_addr";
1c9d54bf
TL
5018
5019 push @$cmd, '-incoming', $migrate_uri;
5020 push @$cmd, '-S';
5021
1e3baf05 5022 } else {
6c47d546 5023 push @$cmd, '-loadstate', $statefile;
1e3baf05 5024 }
91bd6c90
DM
5025 } elsif ($paused) {
5026 push @$cmd, '-S';
1e3baf05
DM
5027 }
5028
1e3baf05 5029 # host pci devices
040b06b7
DA
5030 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
5031 my $d = parse_hostpci($conf->{"hostpci$i"});
5032 next if !$d;
b1f72af6
AD
5033 my $pcidevices = $d->{pciid};
5034 foreach my $pcidevice (@$pcidevices) {
5035 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
000fc0a2 5036
b1f72af6
AD
5037 my $info = pci_device_info("0000:$pciid");
5038 die "IOMMU not present\n" if !check_iommu_support();
5039 die "no pci device info for device '$pciid'\n" if !$info;
6ea8cd3b 5040 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
8f3e88af 5041 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
b1f72af6 5042 }
040b06b7 5043 }
1e3baf05
DM
5044
5045 PVE::Storage::activate_volumes($storecfg, $vollist);
5046
3c23aa80
WB
5047 if (!check_running($vmid, 1)) {
5048 eval {
5049 run_command(['/bin/systemctl', 'stop', "$vmid.scope"],
5050 outfunc => sub {}, errfunc => sub {});
5051 };
2b401189
AD
5052 }
5053
8e59d952
WB
5054 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
5055 : $defaults->{cpuunits};
5056
f38de678
AD
5057 my $start_timeout = $conf->{hugepages} ? 300 : 30;
5058 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
7023f3ea
AD
5059
5060 my %properties = (
5061 Slice => 'qemu.slice',
5062 KillMode => 'none',
5063 CPUShares => $cpuunits
5064 );
5065
5066 if (my $cpulimit = $conf->{cpulimit}) {
5067 $properties{CPUQuota} = int($cpulimit * 100);
5068 }
5069 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
5070
503308ed
WB
5071 my $run_qemu = sub {
5072 PVE::Tools::run_fork sub {
d04d6af1 5073 PVE::Systemd::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
503308ed
WB
5074 run_command($cmd, %run_params);
5075 };
5076 };
5077
7023f3ea
AD
5078 if ($conf->{hugepages}) {
5079
5080 my $code = sub {
5081 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
5082 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
5083
5084 PVE::QemuServer::Memory::hugepages_mount();
5085 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
5086
503308ed 5087 eval { $run_qemu->() };
7023f3ea
AD
5088 if (my $err = $@) {
5089 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
5090 die $err;
5091 }
5092
5093 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
5094 };
5095 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
5096
5097 } else {
503308ed 5098 eval { $run_qemu->() };
7023f3ea 5099 }
77cde36b
DC
5100
5101 if (my $err = $@) {
5102 # deactivate volumes if start fails
5103 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
5104 die "start failed: $err";
5105 }
1e3baf05 5106
5bc1e039 5107 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 5108
b37ecfe6 5109 if ($statefile && $statefile ne 'tcp' && $statefile ne 'unix') {
95381ce0 5110 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 5111 warn $@ if $@;
62de2cbd
DM
5112 }
5113
2189246c
AD
5114 #start nbd server for storage migration
5115 if ($targetstorage) {
2189246c
AD
5116 my $nodename = PVE::INotify::nodename();
5117 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
5118 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
5119 my $pfamily = PVE::Tools::get_host_address_family($nodename);
5120 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
5121
5122 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet', data => { host => "${localip}", port => "${migrate_port}" } } );
5123
5124 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5125
5126 foreach my $opt (sort keys %$local_volumes) {
5127 my $volid = $local_volumes->{$opt};
5128 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
5129 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
5130 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
5131 }
5132 }
5133
1d794448 5134 if ($migratedfrom) {
a89fded1 5135 eval {
8e90138a 5136 set_migration_caps($vmid);
a89fded1 5137 };
1d794448 5138 warn $@ if $@;
a89fded1 5139
1d794448
DM
5140 if ($spice_port) {
5141 print "spice listens on port $spice_port\n";
5142 if ($spice_ticket) {
8e90138a
DM
5143 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
5144 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
5145 }
5146 }
5147
1d794448 5148 } else {
51153f86
DC
5149 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
5150 if !$statefile && $conf->{balloon};
25088687
DM
5151
5152 foreach my $opt (keys %$conf) {
5153 next if $opt !~ m/^net\d+$/;
5154 my $nicconf = parse_net($conf->{$opt});
5155 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
5156 }
e18b0b99 5157 }
a1b7d579 5158
eb065317
AD
5159 vm_mon_cmd_nocheck($vmid, 'qom-set',
5160 path => "machine/peripheral/balloon0",
5161 property => "guest-stats-polling-interval",
5162 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
5163
1e3baf05
DM
5164 });
5165}
5166
0eedc444
AD
5167sub vm_mon_cmd {
5168 my ($vmid, $execute, %params) = @_;
5169
26f11676
DM
5170 my $cmd = { execute => $execute, arguments => \%params };
5171 vm_qmp_command($vmid, $cmd);
0eedc444
AD
5172}
5173
5174sub vm_mon_cmd_nocheck {
5175 my ($vmid, $execute, %params) = @_;
5176
26f11676
DM
5177 my $cmd = { execute => $execute, arguments => \%params };
5178 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
5179}
5180
c971c4f2 5181sub vm_qmp_command {
c5a07de5 5182 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 5183
c971c4f2 5184 my $res;
26f11676 5185
14db5366
DM
5186 my $timeout;
5187 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
5188 $timeout = $cmd->{arguments}->{timeout};
5189 delete $cmd->{arguments}->{timeout};
5190 }
be190583 5191
c971c4f2
AD
5192 eval {
5193 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
7a6c2150
DM
5194 my $sname = qmp_socket($vmid);
5195 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
c5a07de5 5196 my $qmpclient = PVE::QMPClient->new();
dab36e1e 5197
14db5366 5198 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
dab36e1e
DM
5199 } else {
5200 die "unable to open monitor socket\n";
5201 }
c971c4f2 5202 };
26f11676 5203 if (my $err = $@) {
c971c4f2
AD
5204 syslog("err", "VM $vmid qmp command failed - $err");
5205 die $err;
5206 }
5207
5208 return $res;
5209}
5210
9df5cbcc
DM
5211sub vm_human_monitor_command {
5212 my ($vmid, $cmdline) = @_;
5213
5214 my $res;
5215
f5eb281a 5216 my $cmd = {
9df5cbcc
DM
5217 execute => 'human-monitor-command',
5218 arguments => { 'command-line' => $cmdline},
5219 };
5220
5221 return vm_qmp_command($vmid, $cmd);
5222}
5223
1e3baf05
DM
5224sub vm_commandline {
5225 my ($storecfg, $vmid) = @_;
5226
ffda963f 5227 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05
DM
5228
5229 my $defaults = load_defaults();
5230
6b64503e 5231 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 5232
5930c1ff 5233 return PVE::Tools::cmd2string($cmd);
1e3baf05
DM
5234}
5235
5236sub vm_reset {
5237 my ($vmid, $skiplock) = @_;
5238
ffda963f 5239 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5240
ffda963f 5241 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5242
ffda963f 5243 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 5244
816e2c4a 5245 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
5246 });
5247}
5248
5249sub get_vm_volumes {
5250 my ($conf) = @_;
1e3baf05 5251
ff1a2432 5252 my $vollist = [];
d5769dc2 5253 foreach_volid($conf, sub {
392f8b5d 5254 my ($volid, $attr) = @_;
ff1a2432 5255
d5769dc2 5256 return if $volid =~ m|^/|;
ff1a2432 5257
d5769dc2
DM
5258 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
5259 return if !$sid;
ff1a2432
DM
5260
5261 push @$vollist, $volid;
1e3baf05 5262 });
ff1a2432
DM
5263
5264 return $vollist;
5265}
5266
5267sub vm_stop_cleanup {
70b04821 5268 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
ff1a2432 5269
745fed70 5270 eval {
ff1a2432 5271
254575e9
DM
5272 if (!$keepActive) {
5273 my $vollist = get_vm_volumes($conf);
5274 PVE::Storage::deactivate_volumes($storecfg, $vollist);
5275 }
a1b7d579 5276
ab6a046f 5277 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
5278 unlink "/var/run/qemu-server/${vmid}.$ext";
5279 }
a1b7d579 5280
70b04821 5281 vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
745fed70
DM
5282 };
5283 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
5284}
5285
e6c3b671 5286# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
5287# We need that when migration VMs to other nodes (files already moved)
5288# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 5289sub vm_stop {
af30308f 5290 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 5291
9269013a 5292 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 5293
af30308f
DM
5294 if ($migratedfrom){
5295 my $pid = check_running($vmid, $nocheck, $migratedfrom);
5296 kill 15, $pid if $pid;
ffda963f 5297 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
70b04821 5298 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
af30308f
DM
5299 return;
5300 }
5301
ffda963f 5302 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5303
e6c3b671 5304 my $pid = check_running($vmid, $nocheck);
ff1a2432 5305 return if !$pid;
1e3baf05 5306
ff1a2432 5307 my $conf;
e6c3b671 5308 if (!$nocheck) {
ffda963f
FG
5309 $conf = PVE::QemuConfig->load_config($vmid);
5310 PVE::QemuConfig->check_lock($conf) if !$skiplock;
7f4a5b5a 5311 if (!defined($timeout) && $shutdown && $conf->{startup}) {
38f7f26c 5312 my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
7f4a5b5a
DM
5313 $timeout = $opts->{down} if $opts->{down};
5314 }
e6c3b671 5315 }
19672434 5316
7f4a5b5a 5317 $timeout = 60 if !defined($timeout);
67fb9de6 5318
9269013a
DM
5319 eval {
5320 if ($shutdown) {
9d66b397 5321 if (defined($conf) && parse_guest_agent($conf)->{enabled}) {
2ea54503 5322 vm_qmp_command($vmid, { execute => "guest-shutdown" }, $nocheck);
1c0c1c17 5323 } else {
2ea54503 5324 vm_qmp_command($vmid, { execute => "system_powerdown" }, $nocheck);
1c0c1c17 5325 }
9269013a 5326 } else {
2ea54503 5327 vm_qmp_command($vmid, { execute => "quit" }, $nocheck);
afdb31d5 5328 }
9269013a 5329 };
1e3baf05
DM
5330 my $err = $@;
5331
5332 if (!$err) {
1e3baf05 5333 my $count = 0;
e6c3b671 5334 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
5335 $count++;
5336 sleep 1;
5337 }
5338
5339 if ($count >= $timeout) {
9269013a
DM
5340 if ($force) {
5341 warn "VM still running - terminating now with SIGTERM\n";
5342 kill 15, $pid;
5343 } else {
5344 die "VM quit/powerdown failed - got timeout\n";
5345 }
5346 } else {
70b04821 5347 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
9269013a 5348 return;
1e3baf05
DM
5349 }
5350 } else {
9269013a
DM
5351 if ($force) {
5352 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5353 kill 15, $pid;
5354 } else {
afdb31d5 5355 die "VM quit/powerdown failed\n";
9269013a 5356 }
1e3baf05
DM
5357 }
5358
5359 # wait again
ff1a2432 5360 $timeout = 10;
1e3baf05
DM
5361
5362 my $count = 0;
e6c3b671 5363 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
5364 $count++;
5365 sleep 1;
5366 }
5367
5368 if ($count >= $timeout) {
ff1a2432 5369 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 5370 kill 9, $pid;
ff1a2432 5371 sleep 1;
1e3baf05
DM
5372 }
5373
70b04821 5374 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
ff1a2432 5375 });
1e3baf05
DM
5376}
5377
5378sub vm_suspend {
5379 my ($vmid, $skiplock) = @_;
5380
ffda963f 5381 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5382
ffda963f 5383 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5384
e79706d4
FG
5385 PVE::QemuConfig->check_lock($conf)
5386 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
bcb7c9cf 5387
f77f91f3 5388 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
5389 });
5390}
5391
5392sub vm_resume {
289e0b85 5393 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 5394
ffda963f 5395 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5396
c2786bed
DC
5397 my $res = vm_mon_cmd($vmid, 'query-status');
5398 my $resume_cmd = 'cont';
5399
5400 if ($res->{status} && $res->{status} eq 'suspended') {
5401 $resume_cmd = 'system_wakeup';
5402 }
5403
289e0b85 5404 if (!$nocheck) {
1e3baf05 5405
ffda963f 5406 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5407
e79706d4
FG
5408 PVE::QemuConfig->check_lock($conf)
5409 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
289e0b85 5410
c2786bed 5411 vm_mon_cmd($vmid, $resume_cmd);
289e0b85
AD
5412
5413 } else {
c2786bed 5414 vm_mon_cmd_nocheck($vmid, $resume_cmd);
289e0b85 5415 }
1e3baf05
DM
5416 });
5417}
5418
5fdbe4f0
DM
5419sub vm_sendkey {
5420 my ($vmid, $skiplock, $key) = @_;
1e3baf05 5421
ffda963f 5422 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5423
ffda963f 5424 my $conf = PVE::QemuConfig->load_config($vmid);
f5eb281a 5425
7b7c6d1b
DM
5426 # there is no qmp command, so we use the human monitor command
5427 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
5428 });
5429}
5430
5431sub vm_destroy {
5432 my ($storecfg, $vmid, $skiplock) = @_;
5433
ffda963f 5434 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 5435
ffda963f 5436 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 5437
ff1a2432 5438 if (!check_running($vmid)) {
15cc8784 5439 destroy_vm($storecfg, $vmid, undef, $skiplock);
ff1a2432
DM
5440 } else {
5441 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
5442 }
5443 });
5444}
5445
1e3baf05
DM
5446# pci helpers
5447
5448sub file_write {
5449 my ($filename, $buf) = @_;
5450
6b64503e 5451 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
5452 return undef if !$fh;
5453
5454 my $res = print $fh $buf;
5455
5456 $fh->close();
5457
5458 return $res;
5459}
5460
5461sub pci_device_info {
5462 my ($name) = @_;
5463
5464 my $res;
5465
5466 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5467 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5468
5469 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
5470 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5471
5472 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
5473 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5474
5475 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
5476 return undef if !defined($product) || $product !~ s/^0x//;
5477
5478 $res = {
5479 name => $name,
5480 vendor => $vendor,
5481 product => $product,
5482 domain => $domain,
5483 bus => $bus,
5484 slot => $slot,
5485 func => $func,
5486 irq => $irq,
5487 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
5488 };
5489
5490 return $res;
5491}
5492
5493sub pci_dev_reset {
5494 my ($dev) = @_;
5495
5496 my $name = $dev->{name};
5497
5498 my $fn = "$pcisysfs/devices/$name/reset";
5499
6b64503e 5500 return file_write($fn, "1");
1e3baf05
DM
5501}
5502
000fc0a2
SP
5503sub pci_dev_bind_to_vfio {
5504 my ($dev) = @_;
5505
5506 my $name = $dev->{name};
5507
5508 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5509
5510 if (!-d $vfio_basedir) {
5511 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5512 }
5513 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5514
5515 my $testdir = "$vfio_basedir/$name";
5516 return 1 if -d $testdir;
5517
5518 my $data = "$dev->{vendor} $dev->{product}";
5519 return undef if !file_write("$vfio_basedir/new_id", $data);
5520
5521 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5522 if (!file_write($fn, $name)) {
5523 return undef if -f $fn;
5524 }
5525
5526 $fn = "$vfio_basedir/bind";
5527 if (! -d $testdir) {
5528 return undef if !file_write($fn, $name);
5529 }
5530
5531 return -d $testdir;
5532}
5533
5534sub pci_dev_group_bind_to_vfio {
5535 my ($pciid) = @_;
5536
5537 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5538
5539 if (!-d $vfio_basedir) {
5540 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5541 }
5542 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5543
5544 # get IOMMU group devices
5545 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5546 my @devs = grep /^0000:/, readdir($D);
5547 closedir($D);
5548
5549 foreach my $pciid (@devs) {
5550 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
f8fa2ed7
SP
5551
5552 # pci bridges, switches or root ports are not supported
5553 # they have a pci_bus subdirectory so skip them
5554 next if (-e "$pcisysfs/devices/$pciid/pci_bus");
5555
000fc0a2
SP
5556 my $info = pci_device_info($1);
5557 pci_dev_bind_to_vfio($info) || die "Cannot bind $pciid to vfio\n";
5558 }
5559
5560 return 1;
5561}
5562
3e16d5fc
DM
5563# vzdump restore implementaion
5564
ed221350 5565sub tar_archive_read_firstfile {
3e16d5fc 5566 my $archive = shift;
afdb31d5 5567
3e16d5fc
DM
5568 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
5569
5570 # try to detect archive type first
387ba257 5571 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
3e16d5fc 5572 die "unable to open file '$archive'\n";
387ba257 5573 my $firstfile = <$fh>;
3e16d5fc 5574 kill 15, $pid;
387ba257 5575 close $fh;
3e16d5fc
DM
5576
5577 die "ERROR: archive contaions no data\n" if !$firstfile;
5578 chomp $firstfile;
5579
5580 return $firstfile;
5581}
5582
ed221350
DM
5583sub tar_restore_cleanup {
5584 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
5585
5586 print STDERR "starting cleanup\n";
5587
5588 if (my $fd = IO::File->new($statfile, "r")) {
5589 while (defined(my $line = <$fd>)) {
5590 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5591 my $volid = $2;
5592 eval {
5593 if ($volid =~ m|^/|) {
5594 unlink $volid || die 'unlink failed\n';
5595 } else {
ed221350 5596 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 5597 }
afdb31d5 5598 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
5599 };
5600 print STDERR "unable to cleanup '$volid' - $@" if $@;
5601 } else {
5602 print STDERR "unable to parse line in statfile - $line";
afdb31d5 5603 }
3e16d5fc
DM
5604 }
5605 $fd->close();
5606 }
5607}
5608
5609sub restore_archive {
a0d1b1a2 5610 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 5611
91bd6c90
DM
5612 my $format = $opts->{format};
5613 my $comp;
5614
5615 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5616 $format = 'tar' if !$format;
5617 $comp = 'gzip';
5618 } elsif ($archive =~ m/\.tar$/) {
5619 $format = 'tar' if !$format;
5620 } elsif ($archive =~ m/.tar.lzo$/) {
5621 $format = 'tar' if !$format;
5622 $comp = 'lzop';
5623 } elsif ($archive =~ m/\.vma$/) {
5624 $format = 'vma' if !$format;
5625 } elsif ($archive =~ m/\.vma\.gz$/) {
5626 $format = 'vma' if !$format;
5627 $comp = 'gzip';
5628 } elsif ($archive =~ m/\.vma\.lzo$/) {
5629 $format = 'vma' if !$format;
5630 $comp = 'lzop';
5631 } else {
5632 $format = 'vma' if !$format; # default
5633 }
5634
5635 # try to detect archive format
5636 if ($format eq 'tar') {
5637 return restore_tar_archive($archive, $vmid, $user, $opts);
5638 } else {
5639 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
5640 }
5641}
5642
5643sub restore_update_config_line {
5644 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5645
5646 return if $line =~ m/^\#qmdump\#/;
5647 return if $line =~ m/^\#vzdump\#/;
5648 return if $line =~ m/^lock:/;
5649 return if $line =~ m/^unused\d+:/;
5650 return if $line =~ m/^parent:/;
ca3e4fa4 5651 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90 5652
b5b99790 5653 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
91bd6c90
DM
5654 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5655 # try to convert old 1.X settings
5656 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5657 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
5658 my ($model, $macaddr) = split(/\=/, $devconfig);
b5b99790 5659 $macaddr = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if !$macaddr || $unique;
91bd6c90
DM
5660 my $net = {
5661 model => $model,
5662 bridge => "vmbr$ind",
5663 macaddr => $macaddr,
5664 };
5665 my $netstr = print_net($net);
5666
5667 print $outfd "net$cookie->{netcount}: $netstr\n";
5668 $cookie->{netcount}++;
5669 }
5670 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5671 my ($id, $netstr) = ($1, $2);
5672 my $net = parse_net($netstr);
b5b99790 5673 $net->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if $net->{macaddr};
91bd6c90
DM
5674 $netstr = print_net($net);
5675 print $outfd "$id: $netstr\n";
6470743f 5676 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
91bd6c90 5677 my $virtdev = $1;
907ea891 5678 my $value = $3;
d9faf790
WB
5679 my $di = parse_drive($virtdev, $value);
5680 if (defined($di->{backup}) && !$di->{backup}) {
91bd6c90 5681 print $outfd "#$line";
c0f7406e 5682 } elsif ($map->{$virtdev}) {
8fd57431 5683 delete $di->{format}; # format can change on restore
91bd6c90 5684 $di->{file} = $map->{$virtdev};
ed221350 5685 $value = print_drive($vmid, $di);
91bd6c90
DM
5686 print $outfd "$virtdev: $value\n";
5687 } else {
5688 print $outfd $line;
5689 }
1a0c2f03 5690 } elsif (($line =~ m/^vmgenid: (.*)/)) {
babecffe 5691 my $vmgenid = $1;
6ee499ff 5692 if ($vmgenid ne '0') {
1a0c2f03 5693 # always generate a new vmgenid if there was a valid one setup
6ee499ff
DC
5694 $vmgenid = generate_uuid();
5695 }
1a0c2f03 5696 print $outfd "vmgenid: $vmgenid\n";
19a5dd55
WL
5697 } elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
5698 my ($uuid, $uuid_str);
5699 UUID::generate($uuid);
5700 UUID::unparse($uuid, $uuid_str);
5701 my $smbios1 = parse_smbios1($2);
5702 $smbios1->{uuid} = $uuid_str;
5703 print $outfd $1.print_smbios1($smbios1)."\n";
91bd6c90
DM
5704 } else {
5705 print $outfd $line;
5706 }
5707}
5708
5709sub scan_volids {
5710 my ($cfg, $vmid) = @_;
5711
5712 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
5713
5714 my $volid_hash = {};
5715 foreach my $storeid (keys %$info) {
5716 foreach my $item (@{$info->{$storeid}}) {
5717 next if !($item->{volid} && $item->{size});
5996a936 5718 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
5719 $volid_hash->{$item->{volid}} = $item;
5720 }
5721 }
5722
5723 return $volid_hash;
5724}
5725
77019edf
WB
5726sub is_volume_in_use {
5727 my ($storecfg, $conf, $skip_drive, $volid) = @_;
a8e2f942 5728
77019edf 5729 my $path = PVE::Storage::path($storecfg, $volid);
a8e2f942
DM
5730
5731 my $scan_config = sub {
5732 my ($cref, $snapname) = @_;
5733
5734 foreach my $key (keys %$cref) {
5735 my $value = $cref->{$key};
74479ee9 5736 if (is_valid_drivename($key)) {
a8e2f942
DM
5737 next if $skip_drive && $key eq $skip_drive;
5738 my $drive = parse_drive($key, $value);
5739 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
77019edf 5740 return 1 if $volid eq $drive->{file};
a8e2f942 5741 if ($drive->{file} =~ m!^/!) {
77019edf 5742 return 1 if $drive->{file} eq $path;
a8e2f942
DM
5743 } else {
5744 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
5745 next if !$storeid;
5746 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
5747 next if !$scfg;
77019edf 5748 return 1 if $path eq PVE::Storage::path($storecfg, $drive->{file}, $snapname);
a8e2f942
DM
5749 }
5750 }
5751 }
77019edf
WB
5752
5753 return 0;
a8e2f942
DM
5754 };
5755
77019edf 5756 return 1 if &$scan_config($conf);
a8e2f942
DM
5757
5758 undef $skip_drive;
5759
77019edf
WB
5760 foreach my $snapname (keys %{$conf->{snapshots}}) {
5761 return 1 if &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
a8e2f942
DM
5762 }
5763
77019edf 5764 return 0;
a8e2f942
DM
5765}
5766
91bd6c90
DM
5767sub update_disksize {
5768 my ($vmid, $conf, $volid_hash) = @_;
be190583 5769
91bd6c90 5770 my $changes;
53b81297 5771 my $prefix = "VM $vmid:";
91bd6c90 5772
c449137a
DC
5773 # used and unused disks
5774 my $referenced = {};
91bd6c90 5775
5996a936
DM
5776 # Note: it is allowed to define multiple storages with same path (alias), so
5777 # we need to check both 'volid' and real 'path' (two different volid can point
5778 # to the same path).
5779
c449137a 5780 my $referencedpath = {};
be190583 5781
91bd6c90
DM
5782 # update size info
5783 foreach my $opt (keys %$conf) {
74479ee9 5784 if (is_valid_drivename($opt)) {
ed221350 5785 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
5786 my $volid = $drive->{file};
5787 next if !$volid;
5788
c449137a 5789 $referenced->{$volid} = 1;
be190583 5790 if ($volid_hash->{$volid} &&
5996a936 5791 (my $path = $volid_hash->{$volid}->{path})) {
c449137a 5792 $referencedpath->{$path} = 1;
5996a936 5793 }
91bd6c90 5794
ed221350 5795 next if drive_is_cdrom($drive);
91bd6c90
DM
5796 next if !$volid_hash->{$volid};
5797
5798 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
5799 my $new = print_drive($vmid, $drive);
5800 if ($new ne $conf->{$opt}) {
5801 $changes = 1;
5802 $conf->{$opt} = $new;
53b81297 5803 print "$prefix update disk '$opt' information.\n";
7a907ce6 5804 }
91bd6c90
DM
5805 }
5806 }
5807
5996a936
DM
5808 # remove 'unusedX' entry if volume is used
5809 foreach my $opt (keys %$conf) {
5810 next if $opt !~ m/^unused\d+$/;
5811 my $volid = $conf->{$opt};
5812 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
c449137a 5813 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
53b81297 5814 print "$prefix remove entry '$opt', its volume '$volid' is in use.\n";
5996a936
DM
5815 $changes = 1;
5816 delete $conf->{$opt};
5817 }
c449137a
DC
5818
5819 $referenced->{$volid} = 1;
5820 $referencedpath->{$path} = 1 if $path;
5996a936
DM
5821 }
5822
91bd6c90
DM
5823 foreach my $volid (sort keys %$volid_hash) {
5824 next if $volid =~ m/vm-$vmid-state-/;
c449137a 5825 next if $referenced->{$volid};
5996a936
DM
5826 my $path = $volid_hash->{$volid}->{path};
5827 next if !$path; # just to be sure
c449137a 5828 next if $referencedpath->{$path};
91bd6c90 5829 $changes = 1;
53b81297
TL
5830 my $key = PVE::QemuConfig->add_unused_volume($conf, $volid);
5831 print "$prefix add unreferenced volume '$volid' as '$key' to config.\n";
c449137a 5832 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
5833 }
5834
5835 return $changes;
5836}
5837
5838sub rescan {
9224dcee 5839 my ($vmid, $nolock, $dryrun) = @_;
91bd6c90 5840
20519efc 5841 my $cfg = PVE::Storage::config();
91bd6c90 5842
b9a1a3ab
TL
5843 # FIXME: Remove once our RBD plugin can handle CT and VM on a single storage
5844 # see: https://pve.proxmox.com/pipermail/pve-devel/2018-July/032900.html
4771526a
AA
5845 foreach my $stor (keys %{$cfg->{ids}}) {
5846 delete($cfg->{ids}->{$stor}) if ! $cfg->{ids}->{$stor}->{content}->{images};
5847 }
5848
53b81297 5849 print "rescan volumes...\n";
91bd6c90
DM
5850 my $volid_hash = scan_volids($cfg, $vmid);
5851
5852 my $updatefn = sub {
5853 my ($vmid) = @_;
5854
ffda963f 5855 my $conf = PVE::QemuConfig->load_config($vmid);
be190583 5856
ffda963f 5857 PVE::QemuConfig->check_lock($conf);
91bd6c90 5858
03da3f0d
DM
5859 my $vm_volids = {};
5860 foreach my $volid (keys %$volid_hash) {
5861 my $info = $volid_hash->{$volid};
5862 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
5863 }
5864
5865 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 5866
9224dcee 5867 PVE::QemuConfig->write_config($vmid, $conf) if $changes && !$dryrun;
91bd6c90
DM
5868 };
5869
5870 if (defined($vmid)) {
5871 if ($nolock) {
5872 &$updatefn($vmid);
5873 } else {
ffda963f 5874 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
5875 }
5876 } else {
5877 my $vmlist = config_list();
5878 foreach my $vmid (keys %$vmlist) {
5879 if ($nolock) {
5880 &$updatefn($vmid);
5881 } else {
ffda963f 5882 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
be190583 5883 }
91bd6c90
DM
5884 }
5885 }
5886}
5887
5888sub restore_vma_archive {
5889 my ($archive, $vmid, $user, $opts, $comp) = @_;
5890
91bd6c90
DM
5891 my $readfrom = $archive;
5892
7c536e11
WB
5893 my $cfg = PVE::Storage::config();
5894 my $commands = [];
5895 my $bwlimit = $opts->{bwlimit};
5896
5897 my $dbg_cmdstring = '';
5898 my $add_pipe = sub {
5899 my ($cmd) = @_;
5900 push @$commands, $cmd;
5901 $dbg_cmdstring .= ' | ' if length($dbg_cmdstring);
5902 $dbg_cmdstring .= PVE::Tools::cmd2string($cmd);
91bd6c90 5903 $readfrom = '-';
7c536e11
WB
5904 };
5905
5906 my $input = undef;
5907 if ($archive eq '-') {
5908 $input = '<&STDIN';
5909 } else {
5910 # If we use a backup from a PVE defined storage we also consider that
5911 # storage's rate limit:
5912 my (undef, $volid) = PVE::Storage::path_to_volume_id($cfg, $archive);
5913 if (defined($volid)) {
5914 my ($sid, undef) = PVE::Storage::parse_volume_id($volid);
5915 my $readlimit = PVE::Storage::get_bandwidth_limit('restore', [$sid], $bwlimit);
5916 if ($readlimit) {
5917 print STDERR "applying read rate limit: $readlimit\n";
9444c6e4 5918 my $cstream = ['cstream', '-t', $readlimit*1024, '--', $readfrom];
7c536e11
WB
5919 $add_pipe->($cstream);
5920 }
5921 }
5922 }
5923
5924 if ($comp) {
5925 my $cmd;
91bd6c90 5926 if ($comp eq 'gzip') {
7c536e11 5927 $cmd = ['zcat', $readfrom];
91bd6c90 5928 } elsif ($comp eq 'lzop') {
7c536e11 5929 $cmd = ['lzop', '-d', '-c', $readfrom];
91bd6c90
DM
5930 } else {
5931 die "unknown compression method '$comp'\n";
5932 }
7c536e11 5933 $add_pipe->($cmd);
91bd6c90
DM
5934 }
5935
5936 my $tmpdir = "/var/tmp/vzdumptmp$$";
5937 rmtree $tmpdir;
5938
5939 # disable interrupts (always do cleanups)
5b97ef24
TL
5940 local $SIG{INT} =
5941 local $SIG{TERM} =
5942 local $SIG{QUIT} =
5943 local $SIG{HUP} = sub { warn "got interrupt - ignored\n"; };
91bd6c90
DM
5944
5945 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5946 POSIX::mkfifo($mapfifo, 0600);
5947 my $fifofh;
5948
5949 my $openfifo = sub {
5950 open($fifofh, '>', $mapfifo) || die $!;
5951 };
5952
7c536e11 5953 $add_pipe->(['vma', 'extract', '-v', '-r', $mapfifo, $readfrom, $tmpdir]);
91bd6c90
DM
5954
5955 my $oldtimeout;
5956 my $timeout = 5;
5957
5958 my $devinfo = {};
5959
5960 my $rpcenv = PVE::RPCEnvironment::get();
5961
ffda963f 5962 my $conffile = PVE::QemuConfig->config_file($vmid);
91bd6c90
DM
5963 my $tmpfn = "$conffile.$$.tmp";
5964
ed221350 5965 # Note: $oldconf is undef if VM does not exists
ffda963f
FG
5966 my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
5967 my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
ed221350 5968
7c536e11
WB
5969 my %storage_limits;
5970
91bd6c90
DM
5971 my $print_devmap = sub {
5972 my $virtdev_hash = {};
5973
5974 my $cfgfn = "$tmpdir/qemu-server.conf";
5975
5976 # we can read the config - that is already extracted
5977 my $fh = IO::File->new($cfgfn, "r") ||
5978 "unable to read qemu-server.conf - $!\n";
5979
6738ab9c 5980 my $fwcfgfn = "$tmpdir/qemu-server.fw";
3457d090
WL
5981 if (-f $fwcfgfn) {
5982 my $pve_firewall_dir = '/etc/pve/firewall';
5983 mkdir $pve_firewall_dir; # make sure the dir exists
5984 PVE::Tools::file_copy($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5985 }
6738ab9c 5986
91bd6c90
DM
5987 while (defined(my $line = <$fh>)) {
5988 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5989 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5990 die "archive does not contain data for drive '$virtdev'\n"
5991 if !$devinfo->{$devname};
5992 if (defined($opts->{storage})) {
5993 $storeid = $opts->{storage} || 'local';
5994 } elsif (!$storeid) {
5995 $storeid = 'local';
5996 }
5997 $format = 'raw' if !$format;
5998 $devinfo->{$devname}->{devname} = $devname;
5999 $devinfo->{$devname}->{virtdev} = $virtdev;
6000 $devinfo->{$devname}->{format} = $format;
6001 $devinfo->{$devname}->{storeid} = $storeid;
6002
be190583 6003 # check permission on storage
91bd6c90
DM
6004 my $pool = $opts->{pool}; # todo: do we need that?
6005 if ($user ne 'root@pam') {
6006 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
6007 }
6008
7c536e11
WB
6009 $storage_limits{$storeid} = $bwlimit;
6010
91bd6c90
DM
6011 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
6012 }
6013 }
6014
7c536e11
WB
6015 foreach my $key (keys %storage_limits) {
6016 my $limit = PVE::Storage::get_bandwidth_limit('restore', [$key], $bwlimit);
6017 next if !$limit;
6018 print STDERR "rate limit for storage $key: $limit KiB/s\n";
6019 $storage_limits{$key} = $limit * 1024;
6020 }
6021
91bd6c90 6022 foreach my $devname (keys %$devinfo) {
be190583
DM
6023 die "found no device mapping information for device '$devname'\n"
6024 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
6025 }
6026
ed221350 6027 # create empty/temp config
be190583 6028 if ($oldconf) {
ed221350
DM
6029 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
6030 foreach_drive($oldconf, sub {
6031 my ($ds, $drive) = @_;
6032
6033 return if drive_is_cdrom($drive);
6034
6035 my $volid = $drive->{file};
6036
6037 return if !$volid || $volid =~ m|^/|;
6038
6039 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
6040 return if !$path || !$owner || ($owner != $vmid);
6041
6042 # Note: only delete disk we want to restore
6043 # other volumes will become unused
6044 if ($virtdev_hash->{$ds}) {
6b72854b
FG
6045 eval { PVE::Storage::vdisk_free($cfg, $volid); };
6046 if (my $err = $@) {
6047 warn $err;
6048 }
ed221350
DM
6049 }
6050 });
381b8fae
DC
6051
6052 # delete vmstate files
6053 # since after the restore we have no snapshots anymore
6054 foreach my $snapname (keys %{$oldconf->{snapshots}}) {
6055 my $snap = $oldconf->{snapshots}->{$snapname};
6056 if ($snap->{vmstate}) {
6057 eval { PVE::Storage::vdisk_free($cfg, $snap->{vmstate}); };
6058 if (my $err = $@) {
6059 warn $err;
6060 }
6061 }
6062 }
ed221350
DM
6063 }
6064
6065 my $map = {};
91bd6c90
DM
6066 foreach my $virtdev (sort keys %$virtdev_hash) {
6067 my $d = $virtdev_hash->{$virtdev};
6068 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
7c536e11
WB
6069 my $storeid = $d->{storeid};
6070 my $scfg = PVE::Storage::storage_config($cfg, $storeid);
6071
6072 my $map_opts = '';
6073 if (my $limit = $storage_limits{$storeid}) {
6074 $map_opts .= "throttling.bps=$limit:throttling.group=$storeid:";
6075 }
8fd57431
DM
6076
6077 # test if requested format is supported
7c536e11 6078 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $storeid);
8fd57431
DM
6079 my $supported = grep { $_ eq $d->{format} } @$validFormats;
6080 $d->{format} = $defFormat if !$supported;
6081
7c536e11 6082 my $volid = PVE::Storage::vdisk_alloc($cfg, $storeid, $vmid,
91bd6c90
DM
6083 $d->{format}, undef, $alloc_size);
6084 print STDERR "new volume ID is '$volid'\n";
6085 $d->{volid} = $volid;
6086 my $path = PVE::Storage::path($cfg, $volid);
6087
5f96f4df
WL
6088 PVE::Storage::activate_volumes($cfg,[$volid]);
6089
91bd6c90 6090 my $write_zeros = 1;
88240a83 6091 if (PVE::Storage::volume_has_feature($cfg, 'sparseinit', $volid)) {
91bd6c90
DM
6092 $write_zeros = 0;
6093 }
6094
7c536e11 6095 print $fifofh "${map_opts}format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
91bd6c90
DM
6096
6097 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
6098 $map->{$virtdev} = $volid;
6099 }
6100
6101 $fh->seek(0, 0) || die "seek failed - $!\n";
6102
6103 my $outfd = new IO::File ($tmpfn, "w") ||
6104 die "unable to write config for VM $vmid\n";
6105
6106 my $cookie = { netcount => 0 };
6107 while (defined(my $line = <$fh>)) {
be190583 6108 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
6109 }
6110
6111 $fh->close();
6112 $outfd->close();
6113 };
6114
6115 eval {
6116 # enable interrupts
6cb0144a
EK
6117 local $SIG{INT} =
6118 local $SIG{TERM} =
6119 local $SIG{QUIT} =
6120 local $SIG{HUP} =
6121 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
91bd6c90
DM
6122 local $SIG{ALRM} = sub { die "got timeout\n"; };
6123
6124 $oldtimeout = alarm($timeout);
6125
6126 my $parser = sub {
6127 my $line = shift;
6128
6129 print "$line\n";
6130
6131 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
6132 my ($dev_id, $size, $devname) = ($1, $2, $3);
6133 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
6134 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 6135 # we correctly received the vma config, so we can disable
3cf90d7a
DM
6136 # the timeout now for disk allocation (set to 10 minutes, so
6137 # that we always timeout if something goes wrong)
6138 alarm(600);
91bd6c90
DM
6139 &$print_devmap();
6140 print $fifofh "done\n";
6141 my $tmp = $oldtimeout || 0;
6142 $oldtimeout = undef;
6143 alarm($tmp);
6144 close($fifofh);
6145 }
6146 };
be190583 6147
7c536e11
WB
6148 print "restore vma archive: $dbg_cmdstring\n";
6149 run_command($commands, input => $input, outfunc => $parser, afterfork => $openfifo);
91bd6c90
DM
6150 };
6151 my $err = $@;
6152
6153 alarm($oldtimeout) if $oldtimeout;
6154
5f96f4df
WL
6155 my $vollist = [];
6156 foreach my $devname (keys %$devinfo) {
6157 my $volid = $devinfo->{$devname}->{volid};
6158 push @$vollist, $volid if $volid;
6159 }
6160
5f96f4df
WL
6161 PVE::Storage::deactivate_volumes($cfg, $vollist);
6162
91bd6c90
DM
6163 unlink $mapfifo;
6164
6165 if ($err) {
6166 rmtree $tmpdir;
6167 unlink $tmpfn;
6168
91bd6c90
DM
6169 foreach my $devname (keys %$devinfo) {
6170 my $volid = $devinfo->{$devname}->{volid};
6171 next if !$volid;
6172 eval {
6173 if ($volid =~ m|^/|) {
6174 unlink $volid || die 'unlink failed\n';
6175 } else {
6176 PVE::Storage::vdisk_free($cfg, $volid);
6177 }
6178 print STDERR "temporary volume '$volid' sucessfuly removed\n";
6179 };
6180 print STDERR "unable to cleanup '$volid' - $@" if $@;
6181 }
6182 die $err;
6183 }
6184
6185 rmtree $tmpdir;
ed221350
DM
6186
6187 rename($tmpfn, $conffile) ||
91bd6c90
DM
6188 die "unable to commit configuration file '$conffile'\n";
6189
ed221350
DM
6190 PVE::Cluster::cfs_update(); # make sure we read new file
6191
91bd6c90
DM
6192 eval { rescan($vmid, 1); };
6193 warn $@ if $@;
6194}
6195
6196sub restore_tar_archive {
6197 my ($archive, $vmid, $user, $opts) = @_;
6198
9c502e26 6199 if ($archive ne '-') {
ed221350 6200 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
6201 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
6202 if $firstfile ne 'qemu-server.conf';
6203 }
3e16d5fc 6204
20519efc 6205 my $storecfg = PVE::Storage::config();
ebb55558 6206
ed221350 6207 # destroy existing data - keep empty config
ffda963f 6208 my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
ebb55558 6209 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 6210
3e16d5fc
DM
6211 my $tocmd = "/usr/lib/qemu-server/qmextract";
6212
2415a446 6213 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 6214 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
6215 $tocmd .= ' --prealloc' if $opts->{prealloc};
6216 $tocmd .= ' --info' if $opts->{info};
6217
a0d1b1a2 6218 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 6219 # so we pipe to zcat
2415a446
DM
6220 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
6221 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
6222
6223 my $tmpdir = "/var/tmp/vzdumptmp$$";
6224 mkpath $tmpdir;
6225
6226 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
6227 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 6228 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 6229
ffda963f 6230 my $conffile = PVE::QemuConfig->config_file($vmid);
3e16d5fc
DM
6231 my $tmpfn = "$conffile.$$.tmp";
6232
6233 # disable interrupts (always do cleanups)
6cb0144a
EK
6234 local $SIG{INT} =
6235 local $SIG{TERM} =
6236 local $SIG{QUIT} =
6237 local $SIG{HUP} = sub { print STDERR "got interrupt - ignored\n"; };
3e16d5fc 6238
afdb31d5 6239 eval {
3e16d5fc 6240 # enable interrupts
6cb0144a
EK
6241 local $SIG{INT} =
6242 local $SIG{TERM} =
6243 local $SIG{QUIT} =
6244 local $SIG{HUP} =
6245 local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
3e16d5fc 6246
9c502e26
DM
6247 if ($archive eq '-') {
6248 print "extracting archive from STDIN\n";
6249 run_command($cmd, input => "<&STDIN");
6250 } else {
6251 print "extracting archive '$archive'\n";
6252 run_command($cmd);
6253 }
3e16d5fc
DM
6254
6255 return if $opts->{info};
6256
6257 # read new mapping
6258 my $map = {};
6259 my $statfile = "$tmpdir/qmrestore.stat";
6260 if (my $fd = IO::File->new($statfile, "r")) {
6261 while (defined (my $line = <$fd>)) {
6262 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
6263 $map->{$1} = $2 if $1;
6264 } else {
6265 print STDERR "unable to parse line in statfile - $line\n";
6266 }
6267 }
6268 $fd->close();
6269 }
6270
6271 my $confsrc = "$tmpdir/qemu-server.conf";
6272
6273 my $srcfd = new IO::File($confsrc, "r") ||
6274 die "unable to open file '$confsrc'\n";
6275
6276 my $outfd = new IO::File ($tmpfn, "w") ||
6277 die "unable to write config for VM $vmid\n";
6278
91bd6c90 6279 my $cookie = { netcount => 0 };
3e16d5fc 6280 while (defined (my $line = <$srcfd>)) {
be190583 6281 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
6282 }
6283
6284 $srcfd->close();
6285 $outfd->close();
6286 };
6287 my $err = $@;
6288
afdb31d5 6289 if ($err) {
3e16d5fc
DM
6290
6291 unlink $tmpfn;
6292
ed221350 6293 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 6294
3e16d5fc 6295 die $err;
afdb31d5 6296 }
3e16d5fc
DM
6297
6298 rmtree $tmpdir;
6299
6300 rename $tmpfn, $conffile ||
6301 die "unable to commit configuration file '$conffile'\n";
91bd6c90 6302
ed221350
DM
6303 PVE::Cluster::cfs_update(); # make sure we read new file
6304
91bd6c90
DM
6305 eval { rescan($vmid, 1); };
6306 warn $@ if $@;
3e16d5fc
DM
6307};
6308
65a5ce88 6309sub foreach_storage_used_by_vm {
18bfb361
DM
6310 my ($conf, $func) = @_;
6311
6312 my $sidhash = {};
6313
8ddbcf8b
FG
6314 foreach_drive($conf, sub {
6315 my ($ds, $drive) = @_;
6316 return if drive_is_cdrom($drive);
18bfb361
DM
6317
6318 my $volid = $drive->{file};
6319
6320 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 6321 $sidhash->{$sid} = $sid if $sid;
8ddbcf8b 6322 });
18bfb361
DM
6323
6324 foreach my $sid (sort keys %$sidhash) {
6325 &$func($sid);
6326 }
6327}
6328
e5eaa028
WL
6329sub do_snapshots_with_qemu {
6330 my ($storecfg, $volid) = @_;
6331
6332 my $storage_name = PVE::Storage::parse_volume_id($volid);
6333
116da784
WL
6334 if ($qemu_snap_storage->{$storecfg->{ids}->{$storage_name}->{type}}
6335 && !$storecfg->{ids}->{$storage_name}->{krbd}){
e5eaa028
WL
6336 return 1;
6337 }
6338
6339 if ($volid =~ m/\.(qcow2|qed)$/){
6340 return 1;
6341 }
6342
6343 return undef;
6344}
6345
4dcc780c 6346sub qga_check_running {
a4938c72 6347 my ($vmid, $nowarn) = @_;
4dcc780c
WL
6348
6349 eval { vm_mon_cmd($vmid, "guest-ping", timeout => 3); };
6350 if ($@) {
a4938c72 6351 warn "Qemu Guest Agent is not running - $@" if !$nowarn;
4dcc780c
WL
6352 return 0;
6353 }
6354 return 1;
6355}
6356
04a69bb4
AD
6357sub template_create {
6358 my ($vmid, $conf, $disk) = @_;
6359
04a69bb4 6360 my $storecfg = PVE::Storage::config();
04a69bb4 6361
9cd07842
DM
6362 foreach_drive($conf, sub {
6363 my ($ds, $drive) = @_;
6364
6365 return if drive_is_cdrom($drive);
6366 return if $disk && $ds ne $disk;
6367
6368 my $volid = $drive->{file};
bbd56097 6369 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 6370
04a69bb4
AD
6371 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
6372 $drive->{file} = $voliddst;
152fe752 6373 $conf->{$ds} = print_drive($vmid, $drive);
ffda963f 6374 PVE::QemuConfig->write_config($vmid, $conf);
04a69bb4 6375 });
04a69bb4
AD
6376}
6377
5133de42 6378sub qemu_img_convert {
988e2714 6379 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5133de42
AD
6380
6381 my $storecfg = PVE::Storage::config();
6382 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
6383 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
6384
6385 if ($src_storeid && $dst_storeid) {
6bb91c17
DM
6386
6387 PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
6388
5133de42
AD
6389 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
6390 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
6391
6392 my $src_format = qemu_img_format($src_scfg, $src_volname);
6393 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
6394
6395 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
6396 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
6397
6398 my $cmd = [];
eed24303 6399 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
29004a20 6400 push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
d4940091
FG
6401 push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
6402 push @$cmd, '-T', 'none' if $src_scfg->{type} eq 'zfspool';
988e2714
WB
6403 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
6404 if ($is_zero_initialized) {
6405 push @$cmd, "zeroinit:$dst_path";
6406 } else {
6407 push @$cmd, $dst_path;
6408 }
5133de42
AD
6409
6410 my $parser = sub {
6411 my $line = shift;
6412 if($line =~ m/\((\S+)\/100\%\)/){
6413 my $percent = $1;
6414 my $transferred = int($size * $percent / 100);
6415 my $remaining = $size - $transferred;
6416
6417 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6418 }
6419
6420 };
6421
6422 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
6423 my $err = $@;
6424 die "copy failed: $err" if $err;
6425 }
6426}
6427
6428sub qemu_img_format {
6429 my ($scfg, $volname) = @_;
6430
9c52f5ed 6431 if ($scfg->{path} && $volname =~ m/\.($QEMU_FORMAT_RE)$/) {
5133de42 6432 return $1;
be190583 6433 } else {
5133de42 6434 return "raw";
5133de42
AD
6435 }
6436}
6437
cfad42af 6438sub qemu_drive_mirror {
5619e74a 6439 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
cfad42af 6440
5a345967
AD
6441 $jobs = {} if !$jobs;
6442
6443 my $qemu_target;
6444 my $format;
35e4ab04 6445 $jobs->{"drive-$drive"} = {};
152fe752 6446
1e5143de 6447 if ($dst_volid =~ /^nbd:/) {
87955688 6448 $qemu_target = $dst_volid;
5a345967 6449 $format = "nbd";
5a345967 6450 } else {
5a345967
AD
6451 my $storecfg = PVE::Storage::config();
6452 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid);
6453
6454 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
cfad42af 6455
5a345967 6456 $format = qemu_img_format($dst_scfg, $dst_volname);
21ccdb50 6457
5a345967 6458 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
21ccdb50 6459
5a345967
AD
6460 $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
6461 }
988e2714
WB
6462
6463 my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
88383920
DM
6464 $opts->{format} = $format if $format;
6465
5a345967 6466 print "drive mirror is starting for drive-$drive\n";
21ccdb50 6467
5a345967 6468 eval { vm_mon_cmd($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
35e4ab04 6469
5a345967
AD
6470 if (my $err = $@) {
6471 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
6472 die "mirroring error: $err";
6473 }
6474
5619e74a 6475 qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
5a345967
AD
6476}
6477
6478sub qemu_drive_mirror_monitor {
5619e74a 6479 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
2e953867 6480
08ac653f 6481 eval {
5a345967
AD
6482 my $err_complete = 0;
6483
08ac653f 6484 while (1) {
5a345967
AD
6485 die "storage migration timed out\n" if $err_complete > 300;
6486
08ac653f 6487 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
08ac653f 6488
5a345967
AD
6489 my $running_mirror_jobs = {};
6490 foreach my $stat (@$stats) {
6491 next if $stat->{type} ne 'mirror';
6492 $running_mirror_jobs->{$stat->{device}} = $stat;
6493 }
08ac653f 6494
5a345967 6495 my $readycounter = 0;
67fb9de6 6496
5a345967
AD
6497 foreach my $job (keys %$jobs) {
6498
6499 if(defined($jobs->{$job}->{complete}) && !defined($running_mirror_jobs->{$job})) {
6500 print "$job : finished\n";
6501 delete $jobs->{$job};
6502 next;
6503 }
6504
bd2d5fe6 6505 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
f34ebd52 6506
5a345967
AD
6507 my $busy = $running_mirror_jobs->{$job}->{busy};
6508 my $ready = $running_mirror_jobs->{$job}->{ready};
6509 if (my $total = $running_mirror_jobs->{$job}->{len}) {
6510 my $transferred = $running_mirror_jobs->{$job}->{offset} || 0;
6511 my $remaining = $total - $transferred;
6512 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
08ac653f 6513
5a345967
AD
6514 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6515 }
f34ebd52 6516
d1782eba 6517 $readycounter++ if $running_mirror_jobs->{$job}->{ready};
5a345967 6518 }
b467f79a 6519
5a345967
AD
6520 last if scalar(keys %$jobs) == 0;
6521
6522 if ($readycounter == scalar(keys %$jobs)) {
6523 print "all mirroring jobs are ready \n";
6524 last if $skipcomplete; #do the complete later
6525
6526 if ($vmiddst && $vmiddst != $vmid) {
1a988fd2
DC
6527 my $agent_running = $qga && qga_check_running($vmid);
6528 if ($agent_running) {
5619e74a
AD
6529 print "freeze filesystem\n";
6530 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-freeze"); };
6531 } else {
6532 print "suspend vm\n";
6533 eval { PVE::QemuServer::vm_suspend($vmid, 1); };
6534 }
6535
5a345967
AD
6536 # if we clone a disk for a new target vm, we don't switch the disk
6537 PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs);
5619e74a 6538
1a988fd2 6539 if ($agent_running) {
5619e74a
AD
6540 print "unfreeze filesystem\n";
6541 eval { PVE::QemuServer::vm_mon_cmd($vmid, "guest-fsfreeze-thaw"); };
6542 } else {
6543 print "resume vm\n";
6544 eval { PVE::QemuServer::vm_resume($vmid, 1, 1); };
6545 }
6546
2e953867 6547 last;
5a345967
AD
6548 } else {
6549
6550 foreach my $job (keys %$jobs) {
6551 # try to switch the disk if source and destination are on the same guest
bd2d5fe6 6552 print "$job: Completing block job...\n";
5a345967
AD
6553
6554 eval { vm_mon_cmd($vmid, "block-job-complete", device => $job) };
6555 if ($@ =~ m/cannot be completed/) {
bd2d5fe6 6556 print "$job: Block job cannot be completed, try again.\n";
5a345967
AD
6557 $err_complete++;
6558 }else {
bd2d5fe6 6559 print "$job: Completed successfully.\n";
5a345967
AD
6560 $jobs->{$job}->{complete} = 1;
6561 }
6562 }
2e953867 6563 }
08ac653f 6564 }
08ac653f 6565 sleep 1;
cfad42af 6566 }
08ac653f 6567 };
88383920 6568 my $err = $@;
08ac653f 6569
88383920 6570 if ($err) {
5a345967 6571 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
88383920
DM
6572 die "mirroring error: $err";
6573 }
6574
5a345967
AD
6575}
6576
6577sub qemu_blockjobs_cancel {
6578 my ($vmid, $jobs) = @_;
6579
6580 foreach my $job (keys %$jobs) {
bd2d5fe6 6581 print "$job: Cancelling block job\n";
5a345967
AD
6582 eval { vm_mon_cmd($vmid, "block-job-cancel", device => $job); };
6583 $jobs->{$job}->{cancel} = 1;
6584 }
6585
6586 while (1) {
6587 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
6588
6589 my $running_jobs = {};
6590 foreach my $stat (@$stats) {
6591 $running_jobs->{$stat->{device}} = $stat;
6592 }
6593
6594 foreach my $job (keys %$jobs) {
6595
bd2d5fe6
WB
6596 if (defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
6597 print "$job: Done.\n";
5a345967
AD
6598 delete $jobs->{$job};
6599 }
6600 }
6601
6602 last if scalar(keys %$jobs) == 0;
6603
6604 sleep 1;
cfad42af
AD
6605 }
6606}
6607
152fe752 6608sub clone_disk {
be190583 6609 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5619e74a 6610 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
152fe752
DM
6611
6612 my $newvolid;
6613
6614 if (!$full) {
6615 print "create linked clone of drive $drivename ($drive->{file})\n";
258e646c 6616 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
152fe752
DM
6617 push @$newvollist, $newvolid;
6618 } else {
5a345967 6619
152fe752
DM
6620 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
6621 $storeid = $storage if $storage;
6622
44549149 6623 my $dst_format = resolve_dst_disk_format($storecfg, $storeid, $volname, $format);
152fe752
DM
6624 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
6625
6626 print "create full clone of drive $drivename ($drive->{file})\n";
931432bd
WB
6627 my $name = undef;
6628 if (drive_is_cloudinit($drive)) {
6629 $name = "vm-$newvmid-cloudinit";
6630 # cloudinit only supports raw and qcow2 atm:
6631 if ($dst_format eq 'qcow2') {
6632 $name .= '.qcow2';
6633 } elsif ($dst_format ne 'raw') {
6634 die "clone: unhandled format for cloudinit image\n";
6635 }
6636 }
6637 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024));
152fe752
DM
6638 push @$newvollist, $newvolid;
6639
3999f370 6640 PVE::Storage::activate_volumes($storecfg, [$newvolid]);
1dbd6d30 6641
988e2714 6642 my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
152fe752 6643 if (!$running || $snapname) {
988e2714 6644 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit);
152fe752 6645 } else {
2e541679
AD
6646
6647 my $kvmver = get_running_qemu_version ($vmid);
6648 if (!qemu_machine_feature_enabled (undef, $kvmver, 2, 7)) {
961af8a3
WB
6649 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6650 if $drive->{iothread};
2e541679 6651 }
2af848a2 6652
5619e74a 6653 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
be190583 6654 }
152fe752
DM
6655 }
6656
6657 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
6658
6659 my $disk = $drive;
6660 $disk->{format} = undef;
6661 $disk->{file} = $newvolid;
6662 $disk->{size} = $size;
6663
6664 return $disk;
6665}
6666
ff556cf2
DM
6667# this only works if VM is running
6668sub get_current_qemu_machine {
6669 my ($vmid) = @_;
6670
6671 my $cmd = { execute => 'query-machines', arguments => {} };
8e90138a 6672 my $res = vm_qmp_command($vmid, $cmd);
ff556cf2
DM
6673
6674 my ($current, $default);
6675 foreach my $e (@$res) {
6676 $default = $e->{name} if $e->{'is-default'};
6677 $current = $e->{name} if $e->{'is-current'};
6678 }
6679
6680 # fallback to the default machine if current is not supported by qemu
6681 return $current || $default || 'pc';
6682}
6683
98cfd8b6
AD
6684sub get_running_qemu_version {
6685 my ($vmid) = @_;
6686 my $cmd = { execute => 'query-version', arguments => {} };
6687 my $res = vm_qmp_command($vmid, $cmd);
6688 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6689}
6690
23f73120
AD
6691sub qemu_machine_feature_enabled {
6692 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6693
6694 my $current_major;
6695 my $current_minor;
6696
6697 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6698
6699 $current_major = $3;
6700 $current_minor = $4;
6701
6702 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6703
6704 $current_major = $1;
6705 $current_minor = $2;
6706 }
6707
dd84e5ec
WB
6708 return 1 if $current_major > $version_major ||
6709 ($current_major == $version_major &&
6710 $current_minor >= $version_minor);
23f73120
AD
6711}
6712
42dbd2ee
AD
6713sub qemu_machine_pxe {
6714 my ($vmid, $conf, $machine) = @_;
6715
6716 $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine;
6717
3807f3e4
DC
6718 if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
6719 $machine .= '.pxe';
42dbd2ee
AD
6720 }
6721
d1363934 6722 return $machine;
42dbd2ee
AD
6723}
6724
249c4a6c
AD
6725sub qemu_use_old_bios_files {
6726 my ($machine_type) = @_;
6727
6728 return if !$machine_type;
6729
6730 my $use_old_bios_files = undef;
6731
6732 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6733 $machine_type = $1;
6734 $use_old_bios_files = 1;
6735 } else {
74cc511f 6736 my $kvmver = kvm_user_version();
249c4a6c
AD
6737 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6738 # load new efi bios files on migration. So this hack is required to allow
6739 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6740 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
74cc511f 6741 $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
249c4a6c
AD
6742 }
6743
6744 return ($use_old_bios_files, $machine_type);
6745}
6746
3e1f1122
TL
6747sub create_efidisk {
6748 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6749
6750 die "EFI vars default image not found\n" if ! -f $OVMF_VARS;
6751
6752 my $vars_size = PVE::Tools::convert_size(-s $OVMF_VARS, 'b' => 'kb');
6753 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6754 PVE::Storage::activate_volumes($storecfg, [$volid]);
6755
6756 my $path = PVE::Storage::path($storecfg, $volid);
6757 eval {
6758 run_command(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6759 };
6760 die "Copying EFI vars image failed: $@" if $@;
6761
6762 return ($volid, $vars_size);
6763}
6764
4543ecf0
AD
6765sub lspci {
6766
6767 my $devices = {};
6768
6769 dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6770 my (undef, $id, $function) = @_;
6771 my $res = { id => $id, function => $function};
6772 push @{$devices->{$id}}, $res;
6773 });
6774
5ee38471
WB
6775 # Entries should be sorted by functions.
6776 foreach my $id (keys %$devices) {
6777 my $dev = $devices->{$id};
6778 $devices->{$id} = [ sort { $a->{function} <=> $b->{function} } @$dev ];
6779 }
6780
4543ecf0
AD
6781 return $devices;
6782}
6783
22de899a
AD
6784sub vm_iothreads_list {
6785 my ($vmid) = @_;
6786
6787 my $res = vm_mon_cmd($vmid, 'query-iothreads');
6788
6789 my $iothreads = {};
6790 foreach my $iothread (@$res) {
6791 $iothreads->{ $iothread->{id} } = $iothread->{"thread-id"};
6792 }
6793
6794 return $iothreads;
6795}
6796
ee034f5c
AD
6797sub scsihw_infos {
6798 my ($conf, $drive) = @_;
6799
6800 my $maxdev = 0;
6801
7fe1b688 6802 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
ee034f5c 6803 $maxdev = 7;
a1511b3c 6804 } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
ee034f5c
AD
6805 $maxdev = 1;
6806 } else {
6807 $maxdev = 256;
6808 }
6809
6810 my $controller = int($drive->{index} / $maxdev);
a1511b3c 6811 my $controller_prefix = ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') ? "virtioscsi" : "scsihw";
ee034f5c
AD
6812
6813 return ($maxdev, $controller, $controller_prefix);
6814}
a1511b3c 6815
075e8249
PA
6816sub add_hyperv_enlightenments {
6817 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
4317f69f 6818
4317f69f
AD
6819 return if $winversion < 6;
6820 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6821
5aba3953
AD
6822 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6823
4317f69f
AD
6824 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
6825 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6826 push @$cpuFlags , 'hv_vapic';
6827 push @$cpuFlags , 'hv_time';
6828 } else {
6829 push @$cpuFlags , 'hv_spinlocks=0xffff';
6830 }
6831
6832 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
6833 push @$cpuFlags , 'hv_reset';
6834 push @$cpuFlags , 'hv_vpindex';
6835 push @$cpuFlags , 'hv_runtime';
6836 }
6837
6838 if ($winversion >= 7) {
6839 push @$cpuFlags , 'hv_relaxed';
ebb346d6 6840
df648a6a 6841 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 12)) {
ebb346d6
AD
6842 push @$cpuFlags , 'hv_synic';
6843 push @$cpuFlags , 'hv_stimer';
6844 }
4317f69f
AD
6845 }
6846}
6847
6848sub windows_version {
6849 my ($ostype) = @_;
6850
6851 return 0 if !$ostype;
6852
6853 my $winversion = 0;
6854
6855 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6856 $winversion = 5;
6857 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6858 $winversion = 6;
6859 } elsif ($ostype =~ m/^win(\d+)$/) {
6860 $winversion = $1;
6861 }
6862
6863 return $winversion;
6864}
6865
44549149
EK
6866sub resolve_dst_disk_format {
6867 my ($storecfg, $storeid, $src_volname, $format) = @_;
6868 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
6869
6870 if (!$format) {
6871 # if no target format is specified, use the source disk format as hint
6872 if ($src_volname) {
6873 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
6874 $format = qemu_img_format($scfg, $src_volname);
6875 } else {
6876 return $defFormat;
6877 }
6878 }
6879
6880 # test if requested format is supported - else use default
6881 my $supported = grep { $_ eq $format } @$validFormats;
6882 $format = $defFormat if !$supported;
6883 return $format;
6884}
6885
ae2fcb3b
EK
6886sub resolve_first_disk {
6887 my $conf = shift;
6888 my @disks = PVE::QemuServer::valid_drive_names();
6889 my $firstdisk;
6890 foreach my $ds (reverse @disks) {
6891 next if !$conf->{$ds};
6892 my $disk = PVE::QemuServer::parse_drive($ds, $conf->{$ds});
6893 next if PVE::QemuServer::drive_is_cdrom($disk);
6894 $firstdisk = $ds;
6895 }
6896 return $firstdisk;
6897}
6898
6ee499ff 6899sub generate_uuid {
ae2fcb3b
EK
6900 my ($uuid, $uuid_str);
6901 UUID::generate($uuid);
6902 UUID::unparse($uuid, $uuid_str);
6ee499ff
DC
6903 return $uuid_str;
6904}
6905
6906sub generate_smbios1_uuid {
6907 return "uuid=".generate_uuid();
ae2fcb3b
EK
6908}
6909
9c152e87
TL
6910sub nbd_stop {
6911 my ($vmid) = @_;
6912
6913 vm_mon_cmd($vmid, 'nbd-server-stop');
6914}
6915
65e866e5
DM
6916# bash completion helper
6917
6918sub complete_backup_archives {
6919 my ($cmdname, $pname, $cvalue) = @_;
6920
6921 my $cfg = PVE::Storage::config();
6922
6923 my $storeid;
6924
6925 if ($cvalue =~ m/^([^:]+):/) {
6926 $storeid = $1;
6927 }
6928
6929 my $data = PVE::Storage::template_list($cfg, $storeid, 'backup');
6930
6931 my $res = [];
6932 foreach my $id (keys %$data) {
6933 foreach my $item (@{$data->{$id}}) {
6934 next if $item->{format} !~ m/^vma\.(gz|lzo)$/;
6935 push @$res, $item->{volid} if defined($item->{volid});
6936 }
6937 }
6938
6939 return $res;
6940}
6941
6942my $complete_vmid_full = sub {
6943 my ($running) = @_;
6944
6945 my $idlist = vmstatus();
6946
6947 my $res = [];
6948
6949 foreach my $id (keys %$idlist) {
6950 my $d = $idlist->{$id};
6951 if (defined($running)) {
6952 next if $d->{template};
6953 next if $running && $d->{status} ne 'running';
6954 next if !$running && $d->{status} eq 'running';
6955 }
6956 push @$res, $id;
6957
6958 }
6959 return $res;
6960};
6961
6962sub complete_vmid {
6963 return &$complete_vmid_full();
6964}
6965
6966sub complete_vmid_stopped {
6967 return &$complete_vmid_full(0);
6968}
6969
6970sub complete_vmid_running {
6971 return &$complete_vmid_full(1);
6972}
6973
335af808
DM
6974sub complete_storage {
6975
6976 my $cfg = PVE::Storage::config();
6977 my $ids = $cfg->{ids};
6978
6979 my $res = [];
6980 foreach my $sid (keys %$ids) {
6981 next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1);
c4c844ef 6982 next if !$ids->{$sid}->{content}->{images};
335af808
DM
6983 push @$res, $sid;
6984 }
6985
6986 return $res;
6987}
6988
1e3baf05 69891;