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