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