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