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