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