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