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