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