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