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