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