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