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