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