]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
clone live vm : add support for multiple jobs
[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,
2de2d6f7 4452 $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
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
67812f9c 4473 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 4474
1e3baf05 4475 my $migrate_port = 0;
5bc1e039 4476 my $migrate_uri;
1e3baf05
DM
4477 if ($statefile) {
4478 if ($statefile eq 'tcp') {
5bc1e039
SP
4479 my $localip = "localhost";
4480 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
af0eba7e 4481 my $nodename = PVE::INotify::nodename();
2de2d6f7 4482
b7a5a225
TL
4483 if (!defined($migration_type)) {
4484 if (defined($datacenterconf->{migration}->{type})) {
4485 $migration_type = $datacenterconf->{migration}->{type};
4486 } else {
4487 $migration_type = 'secure';
4488 }
4489 }
4490
2de2d6f7
TL
4491 if ($migration_type eq 'insecure') {
4492 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4493 if ($migrate_network_addr) {
4494 $localip = $migrate_network_addr;
4495 } else {
5bc1e039 4496 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
2de2d6f7
TL
4497 }
4498
4499 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5bc1e039 4500 }
2de2d6f7 4501
af0eba7e
WB
4502 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4503 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
407e0b8b 4504 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
4505 push @$cmd, '-incoming', $migrate_uri;
4506 push @$cmd, '-S';
1c9d54bf
TL
4507
4508 } elsif ($statefile eq 'unix') {
4509 # should be default for secure migrations as a ssh TCP forward
4510 # tunnel is not deterministic reliable ready and fails regurarly
4511 # to set up in time, so use UNIX socket forwards
54323eed
TL
4512 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4513 unlink $socket_addr;
4514
4515 $migrate_uri = "unix:$socket_addr";
1c9d54bf
TL
4516
4517 push @$cmd, '-incoming', $migrate_uri;
4518 push @$cmd, '-S';
4519
1e3baf05 4520 } else {
6c47d546 4521 push @$cmd, '-loadstate', $statefile;
1e3baf05 4522 }
91bd6c90
DM
4523 } elsif ($paused) {
4524 push @$cmd, '-S';
1e3baf05
DM
4525 }
4526
1e3baf05 4527 # host pci devices
040b06b7
DA
4528 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4529 my $d = parse_hostpci($conf->{"hostpci$i"});
4530 next if !$d;
b1f72af6
AD
4531 my $pcidevices = $d->{pciid};
4532 foreach my $pcidevice (@$pcidevices) {
4533 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
000fc0a2 4534
b1f72af6
AD
4535 my $info = pci_device_info("0000:$pciid");
4536 die "IOMMU not present\n" if !check_iommu_support();
4537 die "no pci device info for device '$pciid'\n" if !$info;
6ea8cd3b 4538 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
8f3e88af 4539 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
b1f72af6 4540 }
040b06b7 4541 }
1e3baf05
DM
4542
4543 PVE::Storage::activate_volumes($storecfg, $vollist);
4544
2b401189
AD
4545 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4546 my $cmd = [];
4547 push @$cmd, '/bin/systemctl', 'stop', "$vmid.scope";
4548 eval { run_command($cmd); };
4549 }
4550
8e59d952
WB
4551 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4552 : $defaults->{cpuunits};
4553
7023f3ea
AD
4554 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4555
4556 my %properties = (
4557 Slice => 'qemu.slice',
4558 KillMode => 'none',
4559 CPUShares => $cpuunits
4560 );
4561
4562 if (my $cpulimit = $conf->{cpulimit}) {
4563 $properties{CPUQuota} = int($cpulimit * 100);
4564 }
4565 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4566
4567 if ($conf->{hugepages}) {
4568
4569 my $code = sub {
4570 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4571 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4572
4573 PVE::QemuServer::Memory::hugepages_mount();
4574 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4575
4576 eval {
4577 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4578 run_command($cmd, %run_params);
4579 };
4580
4581 if (my $err = $@) {
4582 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4583 die $err;
4584 }
4585
4586 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4587 };
4588 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4589
4590 } else {
4591 eval {
4592 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4593 run_command($cmd, %run_params);
4594 };
4595 }
77cde36b
DC
4596
4597 if (my $err = $@) {
4598 # deactivate volumes if start fails
4599 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4600 die "start failed: $err";
4601 }
1e3baf05 4602
5bc1e039 4603 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 4604
8c609afd 4605 if ($statefile && $statefile ne 'tcp') {
95381ce0 4606 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 4607 warn $@ if $@;
62de2cbd
DM
4608 }
4609
1d794448 4610 if ($migratedfrom) {
a89fded1
AD
4611
4612 eval {
8e90138a 4613 set_migration_caps($vmid);
a89fded1 4614 };
1d794448 4615 warn $@ if $@;
a89fded1 4616
1d794448
DM
4617 if ($spice_port) {
4618 print "spice listens on port $spice_port\n";
4619 if ($spice_ticket) {
8e90138a
DM
4620 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
4621 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
4622 }
4623 }
4624
1d794448 4625 } else {
4ec05c4c 4626
15b1fc93 4627 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
be190583 4628 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4ec05c4c 4629 if $conf->{balloon};
4ec05c4c 4630 }
25088687
DM
4631
4632 foreach my $opt (keys %$conf) {
4633 next if $opt !~ m/^net\d+$/;
4634 my $nicconf = parse_net($conf->{$opt});
4635 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4636 }
e18b0b99 4637 }
a1b7d579 4638
eb065317
AD
4639 vm_mon_cmd_nocheck($vmid, 'qom-set',
4640 path => "machine/peripheral/balloon0",
4641 property => "guest-stats-polling-interval",
4642 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4643
1e3baf05
DM
4644 });
4645}
4646
0eedc444
AD
4647sub vm_mon_cmd {
4648 my ($vmid, $execute, %params) = @_;
4649
26f11676
DM
4650 my $cmd = { execute => $execute, arguments => \%params };
4651 vm_qmp_command($vmid, $cmd);
0eedc444
AD
4652}
4653
4654sub vm_mon_cmd_nocheck {
4655 my ($vmid, $execute, %params) = @_;
4656
26f11676
DM
4657 my $cmd = { execute => $execute, arguments => \%params };
4658 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
4659}
4660
c971c4f2 4661sub vm_qmp_command {
c5a07de5 4662 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 4663
c971c4f2 4664 my $res;
26f11676 4665
14db5366
DM
4666 my $timeout;
4667 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4668 $timeout = $cmd->{arguments}->{timeout};
4669 delete $cmd->{arguments}->{timeout};
4670 }
be190583 4671
c971c4f2
AD
4672 eval {
4673 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
7a6c2150
DM
4674 my $sname = qmp_socket($vmid);
4675 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
c5a07de5 4676 my $qmpclient = PVE::QMPClient->new();
dab36e1e 4677
14db5366 4678 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
c5a07de5 4679 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
dab36e1e
DM
4680 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4681 if scalar(%{$cmd->{arguments}});
4682 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4683 } else {
4684 die "unable to open monitor socket\n";
4685 }
c971c4f2 4686 };
26f11676 4687 if (my $err = $@) {
c971c4f2
AD
4688 syslog("err", "VM $vmid qmp command failed - $err");
4689 die $err;
4690 }
4691
4692 return $res;
4693}
4694
9df5cbcc
DM
4695sub vm_human_monitor_command {
4696 my ($vmid, $cmdline) = @_;
4697
4698 my $res;
4699
f5eb281a 4700 my $cmd = {
9df5cbcc
DM
4701 execute => 'human-monitor-command',
4702 arguments => { 'command-line' => $cmdline},
4703 };
4704
4705 return vm_qmp_command($vmid, $cmd);
4706}
4707
1e3baf05
DM
4708sub vm_commandline {
4709 my ($storecfg, $vmid) = @_;
4710
ffda963f 4711 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05
DM
4712
4713 my $defaults = load_defaults();
4714
6b64503e 4715 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 4716
5930c1ff 4717 return PVE::Tools::cmd2string($cmd);
1e3baf05
DM
4718}
4719
4720sub vm_reset {
4721 my ($vmid, $skiplock) = @_;
4722
ffda963f 4723 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4724
ffda963f 4725 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4726
ffda963f 4727 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4728
816e2c4a 4729 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
4730 });
4731}
4732
4733sub get_vm_volumes {
4734 my ($conf) = @_;
1e3baf05 4735
ff1a2432 4736 my $vollist = [];
d5769dc2
DM
4737 foreach_volid($conf, sub {
4738 my ($volid, $is_cdrom) = @_;
ff1a2432 4739
d5769dc2 4740 return if $volid =~ m|^/|;
ff1a2432 4741
d5769dc2
DM
4742 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4743 return if !$sid;
ff1a2432
DM
4744
4745 push @$vollist, $volid;
1e3baf05 4746 });
ff1a2432
DM
4747
4748 return $vollist;
4749}
4750
4751sub vm_stop_cleanup {
70b04821 4752 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
ff1a2432 4753
745fed70 4754 eval {
ff1a2432 4755
254575e9
DM
4756 if (!$keepActive) {
4757 my $vollist = get_vm_volumes($conf);
4758 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4759 }
a1b7d579 4760
ab6a046f 4761 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
4762 unlink "/var/run/qemu-server/${vmid}.$ext";
4763 }
a1b7d579 4764
70b04821 4765 vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
745fed70
DM
4766 };
4767 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
4768}
4769
e6c3b671 4770# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
4771# We need that when migration VMs to other nodes (files already moved)
4772# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 4773sub vm_stop {
af30308f 4774 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 4775
9269013a 4776 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 4777
af30308f
DM
4778 if ($migratedfrom){
4779 my $pid = check_running($vmid, $nocheck, $migratedfrom);
4780 kill 15, $pid if $pid;
ffda963f 4781 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
70b04821 4782 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
af30308f
DM
4783 return;
4784 }
4785
ffda963f 4786 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4787
e6c3b671 4788 my $pid = check_running($vmid, $nocheck);
ff1a2432 4789 return if !$pid;
1e3baf05 4790
ff1a2432 4791 my $conf;
e6c3b671 4792 if (!$nocheck) {
ffda963f
FG
4793 $conf = PVE::QemuConfig->load_config($vmid);
4794 PVE::QemuConfig->check_lock($conf) if !$skiplock;
7f4a5b5a 4795 if (!defined($timeout) && $shutdown && $conf->{startup}) {
38f7f26c 4796 my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
7f4a5b5a
DM
4797 $timeout = $opts->{down} if $opts->{down};
4798 }
e6c3b671 4799 }
19672434 4800
7f4a5b5a 4801 $timeout = 60 if !defined($timeout);
67fb9de6 4802
9269013a
DM
4803 eval {
4804 if ($shutdown) {
fbda7965 4805 if (defined($conf) && $conf->{agent}) {
2ea54503 4806 vm_qmp_command($vmid, { execute => "guest-shutdown" }, $nocheck);
1c0c1c17 4807 } else {
2ea54503 4808 vm_qmp_command($vmid, { execute => "system_powerdown" }, $nocheck);
1c0c1c17 4809 }
9269013a 4810 } else {
2ea54503 4811 vm_qmp_command($vmid, { execute => "quit" }, $nocheck);
afdb31d5 4812 }
9269013a 4813 };
1e3baf05
DM
4814 my $err = $@;
4815
4816 if (!$err) {
1e3baf05 4817 my $count = 0;
e6c3b671 4818 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4819 $count++;
4820 sleep 1;
4821 }
4822
4823 if ($count >= $timeout) {
9269013a
DM
4824 if ($force) {
4825 warn "VM still running - terminating now with SIGTERM\n";
4826 kill 15, $pid;
4827 } else {
4828 die "VM quit/powerdown failed - got timeout\n";
4829 }
4830 } else {
70b04821 4831 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
9269013a 4832 return;
1e3baf05
DM
4833 }
4834 } else {
9269013a
DM
4835 if ($force) {
4836 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4837 kill 15, $pid;
4838 } else {
afdb31d5 4839 die "VM quit/powerdown failed\n";
9269013a 4840 }
1e3baf05
DM
4841 }
4842
4843 # wait again
ff1a2432 4844 $timeout = 10;
1e3baf05
DM
4845
4846 my $count = 0;
e6c3b671 4847 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4848 $count++;
4849 sleep 1;
4850 }
4851
4852 if ($count >= $timeout) {
ff1a2432 4853 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 4854 kill 9, $pid;
ff1a2432 4855 sleep 1;
1e3baf05
DM
4856 }
4857
70b04821 4858 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
ff1a2432 4859 });
1e3baf05
DM
4860}
4861
4862sub vm_suspend {
4863 my ($vmid, $skiplock) = @_;
4864
ffda963f 4865 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4866
ffda963f 4867 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4868
e79706d4
FG
4869 PVE::QemuConfig->check_lock($conf)
4870 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
bcb7c9cf 4871
f77f91f3 4872 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
4873 });
4874}
4875
4876sub vm_resume {
289e0b85 4877 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 4878
ffda963f 4879 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4880
289e0b85 4881 if (!$nocheck) {
1e3baf05 4882
ffda963f 4883 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4884
e79706d4
FG
4885 PVE::QemuConfig->check_lock($conf)
4886 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
289e0b85
AD
4887
4888 vm_mon_cmd($vmid, "cont");
4889
4890 } else {
4891 vm_mon_cmd_nocheck($vmid, "cont");
4892 }
1e3baf05
DM
4893 });
4894}
4895
5fdbe4f0
DM
4896sub vm_sendkey {
4897 my ($vmid, $skiplock, $key) = @_;
1e3baf05 4898
ffda963f 4899 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4900
ffda963f 4901 my $conf = PVE::QemuConfig->load_config($vmid);
f5eb281a 4902
7b7c6d1b
DM
4903 # there is no qmp command, so we use the human monitor command
4904 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
4905 });
4906}
4907
4908sub vm_destroy {
4909 my ($storecfg, $vmid, $skiplock) = @_;
4910
ffda963f 4911 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4912
ffda963f 4913 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4914
ff1a2432 4915 if (!check_running($vmid)) {
15cc8784 4916 destroy_vm($storecfg, $vmid, undef, $skiplock);
ff1a2432
DM
4917 } else {
4918 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
4919 }
4920 });
4921}
4922
1e3baf05
DM
4923# pci helpers
4924
4925sub file_write {
4926 my ($filename, $buf) = @_;
4927
6b64503e 4928 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
4929 return undef if !$fh;
4930
4931 my $res = print $fh $buf;
4932
4933 $fh->close();
4934
4935 return $res;
4936}
4937
4938sub pci_device_info {
4939 my ($name) = @_;
4940
4941 my $res;
4942
4943 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4944 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4945
4946 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
4947 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4948
4949 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
4950 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4951
4952 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
4953 return undef if !defined($product) || $product !~ s/^0x//;
4954
4955 $res = {
4956 name => $name,
4957 vendor => $vendor,
4958 product => $product,
4959 domain => $domain,
4960 bus => $bus,
4961 slot => $slot,
4962 func => $func,
4963 irq => $irq,
4964 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
4965 };
4966
4967 return $res;
4968}
4969
4970sub pci_dev_reset {
4971 my ($dev) = @_;
4972
4973 my $name = $dev->{name};
4974
4975 my $fn = "$pcisysfs/devices/$name/reset";
4976
6b64503e 4977 return file_write($fn, "1");
1e3baf05
DM
4978}
4979
000fc0a2
SP
4980sub pci_dev_bind_to_vfio {
4981 my ($dev) = @_;
4982
4983 my $name = $dev->{name};
4984
4985 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4986
4987 if (!-d $vfio_basedir) {
4988 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4989 }
4990 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
4991
4992 my $testdir = "$vfio_basedir/$name";
4993 return 1 if -d $testdir;
4994
4995 my $data = "$dev->{vendor} $dev->{product}";
4996 return undef if !file_write("$vfio_basedir/new_id", $data);
4997
4998 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4999 if (!file_write($fn, $name)) {
5000 return undef if -f $fn;
5001 }
5002
5003 $fn = "$vfio_basedir/bind";
5004 if (! -d $testdir) {
5005 return undef if !file_write($fn, $name);
5006 }
5007
5008 return -d $testdir;
5009}
5010
5011sub pci_dev_group_bind_to_vfio {
5012 my ($pciid) = @_;
5013
5014 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5015
5016 if (!-d $vfio_basedir) {
5017 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5018 }
5019 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5020
5021 # get IOMMU group devices
5022 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5023 my @devs = grep /^0000:/, readdir($D);
5024 closedir($D);
5025
5026 foreach my $pciid (@devs) {
5027 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
f8fa2ed7
SP
5028
5029 # pci bridges, switches or root ports are not supported
5030 # they have a pci_bus subdirectory so skip them
5031 next if (-e "$pcisysfs/devices/$pciid/pci_bus");
5032
000fc0a2
SP
5033 my $info = pci_device_info($1);
5034 pci_dev_bind_to_vfio($info) || die "Cannot bind $pciid to vfio\n";
5035 }
5036
5037 return 1;
5038}
5039
3e16d5fc
DM
5040# vzdump restore implementaion
5041
ed221350 5042sub tar_archive_read_firstfile {
3e16d5fc 5043 my $archive = shift;
afdb31d5 5044
3e16d5fc
DM
5045 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
5046
5047 # try to detect archive type first
387ba257 5048 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
3e16d5fc 5049 die "unable to open file '$archive'\n";
387ba257 5050 my $firstfile = <$fh>;
3e16d5fc 5051 kill 15, $pid;
387ba257 5052 close $fh;
3e16d5fc
DM
5053
5054 die "ERROR: archive contaions no data\n" if !$firstfile;
5055 chomp $firstfile;
5056
5057 return $firstfile;
5058}
5059
ed221350
DM
5060sub tar_restore_cleanup {
5061 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
5062
5063 print STDERR "starting cleanup\n";
5064
5065 if (my $fd = IO::File->new($statfile, "r")) {
5066 while (defined(my $line = <$fd>)) {
5067 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5068 my $volid = $2;
5069 eval {
5070 if ($volid =~ m|^/|) {
5071 unlink $volid || die 'unlink failed\n';
5072 } else {
ed221350 5073 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 5074 }
afdb31d5 5075 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
5076 };
5077 print STDERR "unable to cleanup '$volid' - $@" if $@;
5078 } else {
5079 print STDERR "unable to parse line in statfile - $line";
afdb31d5 5080 }
3e16d5fc
DM
5081 }
5082 $fd->close();
5083 }
5084}
5085
5086sub restore_archive {
a0d1b1a2 5087 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 5088
91bd6c90
DM
5089 my $format = $opts->{format};
5090 my $comp;
5091
5092 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5093 $format = 'tar' if !$format;
5094 $comp = 'gzip';
5095 } elsif ($archive =~ m/\.tar$/) {
5096 $format = 'tar' if !$format;
5097 } elsif ($archive =~ m/.tar.lzo$/) {
5098 $format = 'tar' if !$format;
5099 $comp = 'lzop';
5100 } elsif ($archive =~ m/\.vma$/) {
5101 $format = 'vma' if !$format;
5102 } elsif ($archive =~ m/\.vma\.gz$/) {
5103 $format = 'vma' if !$format;
5104 $comp = 'gzip';
5105 } elsif ($archive =~ m/\.vma\.lzo$/) {
5106 $format = 'vma' if !$format;
5107 $comp = 'lzop';
5108 } else {
5109 $format = 'vma' if !$format; # default
5110 }
5111
5112 # try to detect archive format
5113 if ($format eq 'tar') {
5114 return restore_tar_archive($archive, $vmid, $user, $opts);
5115 } else {
5116 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
5117 }
5118}
5119
5120sub restore_update_config_line {
5121 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5122
5123 return if $line =~ m/^\#qmdump\#/;
5124 return if $line =~ m/^\#vzdump\#/;
5125 return if $line =~ m/^lock:/;
5126 return if $line =~ m/^unused\d+:/;
5127 return if $line =~ m/^parent:/;
ca3e4fa4 5128 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90 5129
b5b99790 5130 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
91bd6c90
DM
5131 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5132 # try to convert old 1.X settings
5133 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5134 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
5135 my ($model, $macaddr) = split(/\=/, $devconfig);
b5b99790 5136 $macaddr = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if !$macaddr || $unique;
91bd6c90
DM
5137 my $net = {
5138 model => $model,
5139 bridge => "vmbr$ind",
5140 macaddr => $macaddr,
5141 };
5142 my $netstr = print_net($net);
5143
5144 print $outfd "net$cookie->{netcount}: $netstr\n";
5145 $cookie->{netcount}++;
5146 }
5147 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5148 my ($id, $netstr) = ($1, $2);
5149 my $net = parse_net($netstr);
b5b99790 5150 $net->{macaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix}) if $net->{macaddr};
91bd6c90
DM
5151 $netstr = print_net($net);
5152 print $outfd "$id: $netstr\n";
6470743f 5153 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
91bd6c90 5154 my $virtdev = $1;
907ea891 5155 my $value = $3;
d9faf790
WB
5156 my $di = parse_drive($virtdev, $value);
5157 if (defined($di->{backup}) && !$di->{backup}) {
91bd6c90 5158 print $outfd "#$line";
c0f7406e 5159 } elsif ($map->{$virtdev}) {
8fd57431 5160 delete $di->{format}; # format can change on restore
91bd6c90 5161 $di->{file} = $map->{$virtdev};
ed221350 5162 $value = print_drive($vmid, $di);
91bd6c90
DM
5163 print $outfd "$virtdev: $value\n";
5164 } else {
5165 print $outfd $line;
5166 }
5167 } else {
5168 print $outfd $line;
5169 }
5170}
5171
5172sub scan_volids {
5173 my ($cfg, $vmid) = @_;
5174
5175 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
5176
5177 my $volid_hash = {};
5178 foreach my $storeid (keys %$info) {
5179 foreach my $item (@{$info->{$storeid}}) {
5180 next if !($item->{volid} && $item->{size});
5996a936 5181 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
5182 $volid_hash->{$item->{volid}} = $item;
5183 }
5184 }
5185
5186 return $volid_hash;
5187}
5188
77019edf
WB
5189sub is_volume_in_use {
5190 my ($storecfg, $conf, $skip_drive, $volid) = @_;
a8e2f942 5191
77019edf 5192 my $path = PVE::Storage::path($storecfg, $volid);
a8e2f942
DM
5193
5194 my $scan_config = sub {
5195 my ($cref, $snapname) = @_;
5196
5197 foreach my $key (keys %$cref) {
5198 my $value = $cref->{$key};
74479ee9 5199 if (is_valid_drivename($key)) {
a8e2f942
DM
5200 next if $skip_drive && $key eq $skip_drive;
5201 my $drive = parse_drive($key, $value);
5202 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
77019edf 5203 return 1 if $volid eq $drive->{file};
a8e2f942 5204 if ($drive->{file} =~ m!^/!) {
77019edf 5205 return 1 if $drive->{file} eq $path;
a8e2f942
DM
5206 } else {
5207 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
5208 next if !$storeid;
5209 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
5210 next if !$scfg;
77019edf 5211 return 1 if $path eq PVE::Storage::path($storecfg, $drive->{file}, $snapname);
a8e2f942
DM
5212 }
5213 }
5214 }
77019edf
WB
5215
5216 return 0;
a8e2f942
DM
5217 };
5218
77019edf 5219 return 1 if &$scan_config($conf);
a8e2f942
DM
5220
5221 undef $skip_drive;
5222
77019edf
WB
5223 foreach my $snapname (keys %{$conf->{snapshots}}) {
5224 return 1 if &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
a8e2f942
DM
5225 }
5226
77019edf 5227 return 0;
a8e2f942
DM
5228}
5229
91bd6c90
DM
5230sub update_disksize {
5231 my ($vmid, $conf, $volid_hash) = @_;
be190583 5232
91bd6c90
DM
5233 my $changes;
5234
5235 my $used = {};
5236
5996a936
DM
5237 # Note: it is allowed to define multiple storages with same path (alias), so
5238 # we need to check both 'volid' and real 'path' (two different volid can point
5239 # to the same path).
5240
5241 my $usedpath = {};
be190583 5242
91bd6c90
DM
5243 # update size info
5244 foreach my $opt (keys %$conf) {
74479ee9 5245 if (is_valid_drivename($opt)) {
ed221350 5246 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
5247 my $volid = $drive->{file};
5248 next if !$volid;
5249
5250 $used->{$volid} = 1;
be190583 5251 if ($volid_hash->{$volid} &&
5996a936
DM
5252 (my $path = $volid_hash->{$volid}->{path})) {
5253 $usedpath->{$path} = 1;
5254 }
91bd6c90 5255
ed221350 5256 next if drive_is_cdrom($drive);
91bd6c90
DM
5257 next if !$volid_hash->{$volid};
5258
5259 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
5260 my $new = print_drive($vmid, $drive);
5261 if ($new ne $conf->{$opt}) {
5262 $changes = 1;
5263 $conf->{$opt} = $new;
5264 }
91bd6c90
DM
5265 }
5266 }
5267
5996a936
DM
5268 # remove 'unusedX' entry if volume is used
5269 foreach my $opt (keys %$conf) {
5270 next if $opt !~ m/^unused\d+$/;
5271 my $volid = $conf->{$opt};
5272 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
be190583 5273 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5996a936
DM
5274 $changes = 1;
5275 delete $conf->{$opt};
5276 }
5277 }
5278
91bd6c90
DM
5279 foreach my $volid (sort keys %$volid_hash) {
5280 next if $volid =~ m/vm-$vmid-state-/;
5281 next if $used->{$volid};
5996a936
DM
5282 my $path = $volid_hash->{$volid}->{path};
5283 next if !$path; # just to be sure
5284 next if $usedpath->{$path};
91bd6c90 5285 $changes = 1;
8793d495 5286 PVE::QemuConfig->add_unused_volume($conf, $volid);
05937a14 5287 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
5288 }
5289
5290 return $changes;
5291}
5292
5293sub rescan {
5294 my ($vmid, $nolock) = @_;
5295
20519efc 5296 my $cfg = PVE::Storage::config();
91bd6c90
DM
5297
5298 my $volid_hash = scan_volids($cfg, $vmid);
5299
5300 my $updatefn = sub {
5301 my ($vmid) = @_;
5302
ffda963f 5303 my $conf = PVE::QemuConfig->load_config($vmid);
be190583 5304
ffda963f 5305 PVE::QemuConfig->check_lock($conf);
91bd6c90 5306
03da3f0d
DM
5307 my $vm_volids = {};
5308 foreach my $volid (keys %$volid_hash) {
5309 my $info = $volid_hash->{$volid};
5310 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
5311 }
5312
5313 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 5314
ffda963f 5315 PVE::QemuConfig->write_config($vmid, $conf) if $changes;
91bd6c90
DM
5316 };
5317
5318 if (defined($vmid)) {
5319 if ($nolock) {
5320 &$updatefn($vmid);
5321 } else {
ffda963f 5322 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
5323 }
5324 } else {
5325 my $vmlist = config_list();
5326 foreach my $vmid (keys %$vmlist) {
5327 if ($nolock) {
5328 &$updatefn($vmid);
5329 } else {
ffda963f 5330 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
be190583 5331 }
91bd6c90
DM
5332 }
5333 }
5334}
5335
5336sub restore_vma_archive {
5337 my ($archive, $vmid, $user, $opts, $comp) = @_;
5338
5339 my $input = $archive eq '-' ? "<&STDIN" : undef;
5340 my $readfrom = $archive;
5341
5342 my $uncomp = '';
5343 if ($comp) {
5344 $readfrom = '-';
5345 my $qarchive = PVE::Tools::shellquote($archive);
5346 if ($comp eq 'gzip') {
5347 $uncomp = "zcat $qarchive|";
5348 } elsif ($comp eq 'lzop') {
5349 $uncomp = "lzop -d -c $qarchive|";
5350 } else {
5351 die "unknown compression method '$comp'\n";
5352 }
be190583 5353
91bd6c90
DM
5354 }
5355
5356 my $tmpdir = "/var/tmp/vzdumptmp$$";
5357 rmtree $tmpdir;
5358
5359 # disable interrupts (always do cleanups)
5360 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
5361 warn "got interrupt - ignored\n";
5362 };
5363
5364 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5365 POSIX::mkfifo($mapfifo, 0600);
5366 my $fifofh;
5367
5368 my $openfifo = sub {
5369 open($fifofh, '>', $mapfifo) || die $!;
5370 };
5371
5372 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5373
5374 my $oldtimeout;
5375 my $timeout = 5;
5376
5377 my $devinfo = {};
5378
5379 my $rpcenv = PVE::RPCEnvironment::get();
5380
ffda963f 5381 my $conffile = PVE::QemuConfig->config_file($vmid);
91bd6c90
DM
5382 my $tmpfn = "$conffile.$$.tmp";
5383
ed221350 5384 # Note: $oldconf is undef if VM does not exists
ffda963f
FG
5385 my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
5386 my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
ed221350 5387
91bd6c90
DM
5388 my $print_devmap = sub {
5389 my $virtdev_hash = {};
5390
5391 my $cfgfn = "$tmpdir/qemu-server.conf";
5392
5393 # we can read the config - that is already extracted
5394 my $fh = IO::File->new($cfgfn, "r") ||
5395 "unable to read qemu-server.conf - $!\n";
5396
6738ab9c 5397 my $fwcfgfn = "$tmpdir/qemu-server.fw";
3457d090
WL
5398 if (-f $fwcfgfn) {
5399 my $pve_firewall_dir = '/etc/pve/firewall';
5400 mkdir $pve_firewall_dir; # make sure the dir exists
5401 PVE::Tools::file_copy($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5402 }
6738ab9c 5403
91bd6c90
DM
5404 while (defined(my $line = <$fh>)) {
5405 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5406 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5407 die "archive does not contain data for drive '$virtdev'\n"
5408 if !$devinfo->{$devname};
5409 if (defined($opts->{storage})) {
5410 $storeid = $opts->{storage} || 'local';
5411 } elsif (!$storeid) {
5412 $storeid = 'local';
5413 }
5414 $format = 'raw' if !$format;
5415 $devinfo->{$devname}->{devname} = $devname;
5416 $devinfo->{$devname}->{virtdev} = $virtdev;
5417 $devinfo->{$devname}->{format} = $format;
5418 $devinfo->{$devname}->{storeid} = $storeid;
5419
be190583 5420 # check permission on storage
91bd6c90
DM
5421 my $pool = $opts->{pool}; # todo: do we need that?
5422 if ($user ne 'root@pam') {
5423 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5424 }
5425
5426 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5427 }
5428 }
5429
5430 foreach my $devname (keys %$devinfo) {
be190583
DM
5431 die "found no device mapping information for device '$devname'\n"
5432 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
5433 }
5434
20519efc 5435 my $cfg = PVE::Storage::config();
ed221350
DM
5436
5437 # create empty/temp config
be190583 5438 if ($oldconf) {
ed221350
DM
5439 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
5440 foreach_drive($oldconf, sub {
5441 my ($ds, $drive) = @_;
5442
5443 return if drive_is_cdrom($drive);
5444
5445 my $volid = $drive->{file};
5446
5447 return if !$volid || $volid =~ m|^/|;
5448
5449 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
5450 return if !$path || !$owner || ($owner != $vmid);
5451
5452 # Note: only delete disk we want to restore
5453 # other volumes will become unused
5454 if ($virtdev_hash->{$ds}) {
6b72854b
FG
5455 eval { PVE::Storage::vdisk_free($cfg, $volid); };
5456 if (my $err = $@) {
5457 warn $err;
5458 }
ed221350
DM
5459 }
5460 });
381b8fae
DC
5461
5462 # delete vmstate files
5463 # since after the restore we have no snapshots anymore
5464 foreach my $snapname (keys %{$oldconf->{snapshots}}) {
5465 my $snap = $oldconf->{snapshots}->{$snapname};
5466 if ($snap->{vmstate}) {
5467 eval { PVE::Storage::vdisk_free($cfg, $snap->{vmstate}); };
5468 if (my $err = $@) {
5469 warn $err;
5470 }
5471 }
5472 }
ed221350
DM
5473 }
5474
5475 my $map = {};
91bd6c90
DM
5476 foreach my $virtdev (sort keys %$virtdev_hash) {
5477 my $d = $virtdev_hash->{$virtdev};
5478 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
5479 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
8fd57431
DM
5480
5481 # test if requested format is supported
5482 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
5483 my $supported = grep { $_ eq $d->{format} } @$validFormats;
5484 $d->{format} = $defFormat if !$supported;
5485
91bd6c90
DM
5486 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
5487 $d->{format}, undef, $alloc_size);
5488 print STDERR "new volume ID is '$volid'\n";
5489 $d->{volid} = $volid;
5490 my $path = PVE::Storage::path($cfg, $volid);
5491
5f96f4df
WL
5492 PVE::Storage::activate_volumes($cfg,[$volid]);
5493
91bd6c90 5494 my $write_zeros = 1;
88240a83 5495 if (PVE::Storage::volume_has_feature($cfg, 'sparseinit', $volid)) {
91bd6c90
DM
5496 $write_zeros = 0;
5497 }
5498
3c525055 5499 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
91bd6c90
DM
5500
5501 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5502 $map->{$virtdev} = $volid;
5503 }
5504
5505 $fh->seek(0, 0) || die "seek failed - $!\n";
5506
5507 my $outfd = new IO::File ($tmpfn, "w") ||
5508 die "unable to write config for VM $vmid\n";
5509
5510 my $cookie = { netcount => 0 };
5511 while (defined(my $line = <$fh>)) {
be190583 5512 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
5513 }
5514
5515 $fh->close();
5516 $outfd->close();
5517 };
5518
5519 eval {
5520 # enable interrupts
5521 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
5522 die "interrupted by signal\n";
5523 };
5524 local $SIG{ALRM} = sub { die "got timeout\n"; };
5525
5526 $oldtimeout = alarm($timeout);
5527
5528 my $parser = sub {
5529 my $line = shift;
5530
5531 print "$line\n";
5532
5533 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5534 my ($dev_id, $size, $devname) = ($1, $2, $3);
5535 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
5536 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 5537 # we correctly received the vma config, so we can disable
3cf90d7a
DM
5538 # the timeout now for disk allocation (set to 10 minutes, so
5539 # that we always timeout if something goes wrong)
5540 alarm(600);
91bd6c90
DM
5541 &$print_devmap();
5542 print $fifofh "done\n";
5543 my $tmp = $oldtimeout || 0;
5544 $oldtimeout = undef;
5545 alarm($tmp);
5546 close($fifofh);
5547 }
5548 };
be190583 5549
91bd6c90
DM
5550 print "restore vma archive: $cmd\n";
5551 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
5552 };
5553 my $err = $@;
5554
5555 alarm($oldtimeout) if $oldtimeout;
5556
5f96f4df
WL
5557 my $vollist = [];
5558 foreach my $devname (keys %$devinfo) {
5559 my $volid = $devinfo->{$devname}->{volid};
5560 push @$vollist, $volid if $volid;
5561 }
5562
20519efc 5563 my $cfg = PVE::Storage::config();
5f96f4df
WL
5564 PVE::Storage::deactivate_volumes($cfg, $vollist);
5565
91bd6c90
DM
5566 unlink $mapfifo;
5567
5568 if ($err) {
5569 rmtree $tmpdir;
5570 unlink $tmpfn;
5571
91bd6c90
DM
5572 foreach my $devname (keys %$devinfo) {
5573 my $volid = $devinfo->{$devname}->{volid};
5574 next if !$volid;
5575 eval {
5576 if ($volid =~ m|^/|) {
5577 unlink $volid || die 'unlink failed\n';
5578 } else {
5579 PVE::Storage::vdisk_free($cfg, $volid);
5580 }
5581 print STDERR "temporary volume '$volid' sucessfuly removed\n";
5582 };
5583 print STDERR "unable to cleanup '$volid' - $@" if $@;
5584 }
5585 die $err;
5586 }
5587
5588 rmtree $tmpdir;
ed221350
DM
5589
5590 rename($tmpfn, $conffile) ||
91bd6c90
DM
5591 die "unable to commit configuration file '$conffile'\n";
5592
ed221350
DM
5593 PVE::Cluster::cfs_update(); # make sure we read new file
5594
91bd6c90
DM
5595 eval { rescan($vmid, 1); };
5596 warn $@ if $@;
5597}
5598
5599sub restore_tar_archive {
5600 my ($archive, $vmid, $user, $opts) = @_;
5601
9c502e26 5602 if ($archive ne '-') {
ed221350 5603 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
5604 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5605 if $firstfile ne 'qemu-server.conf';
5606 }
3e16d5fc 5607
20519efc 5608 my $storecfg = PVE::Storage::config();
ebb55558 5609
ed221350 5610 # destroy existing data - keep empty config
ffda963f 5611 my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
ebb55558 5612 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 5613
3e16d5fc
DM
5614 my $tocmd = "/usr/lib/qemu-server/qmextract";
5615
2415a446 5616 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 5617 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
5618 $tocmd .= ' --prealloc' if $opts->{prealloc};
5619 $tocmd .= ' --info' if $opts->{info};
5620
a0d1b1a2 5621 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 5622 # so we pipe to zcat
2415a446
DM
5623 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
5624 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
5625
5626 my $tmpdir = "/var/tmp/vzdumptmp$$";
5627 mkpath $tmpdir;
5628
5629 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
5630 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 5631 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 5632
ffda963f 5633 my $conffile = PVE::QemuConfig->config_file($vmid);
3e16d5fc
DM
5634 my $tmpfn = "$conffile.$$.tmp";
5635
5636 # disable interrupts (always do cleanups)
5637 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
5638 print STDERR "got interrupt - ignored\n";
5639 };
5640
afdb31d5 5641 eval {
3e16d5fc
DM
5642 # enable interrupts
5643 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
5644 die "interrupted by signal\n";
5645 };
5646
9c502e26
DM
5647 if ($archive eq '-') {
5648 print "extracting archive from STDIN\n";
5649 run_command($cmd, input => "<&STDIN");
5650 } else {
5651 print "extracting archive '$archive'\n";
5652 run_command($cmd);
5653 }
3e16d5fc
DM
5654
5655 return if $opts->{info};
5656
5657 # read new mapping
5658 my $map = {};
5659 my $statfile = "$tmpdir/qmrestore.stat";
5660 if (my $fd = IO::File->new($statfile, "r")) {
5661 while (defined (my $line = <$fd>)) {
5662 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5663 $map->{$1} = $2 if $1;
5664 } else {
5665 print STDERR "unable to parse line in statfile - $line\n";
5666 }
5667 }
5668 $fd->close();
5669 }
5670
5671 my $confsrc = "$tmpdir/qemu-server.conf";
5672
5673 my $srcfd = new IO::File($confsrc, "r") ||
5674 die "unable to open file '$confsrc'\n";
5675
5676 my $outfd = new IO::File ($tmpfn, "w") ||
5677 die "unable to write config for VM $vmid\n";
5678
91bd6c90 5679 my $cookie = { netcount => 0 };
3e16d5fc 5680 while (defined (my $line = <$srcfd>)) {
be190583 5681 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
5682 }
5683
5684 $srcfd->close();
5685 $outfd->close();
5686 };
5687 my $err = $@;
5688
afdb31d5 5689 if ($err) {
3e16d5fc
DM
5690
5691 unlink $tmpfn;
5692
ed221350 5693 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 5694
3e16d5fc 5695 die $err;
afdb31d5 5696 }
3e16d5fc
DM
5697
5698 rmtree $tmpdir;
5699
5700 rename $tmpfn, $conffile ||
5701 die "unable to commit configuration file '$conffile'\n";
91bd6c90 5702
ed221350
DM
5703 PVE::Cluster::cfs_update(); # make sure we read new file
5704
91bd6c90
DM
5705 eval { rescan($vmid, 1); };
5706 warn $@ if $@;
3e16d5fc
DM
5707};
5708
18bfb361
DM
5709sub foreach_writable_storage {
5710 my ($conf, $func) = @_;
5711
5712 my $sidhash = {};
5713
5714 foreach my $ds (keys %$conf) {
74479ee9 5715 next if !is_valid_drivename($ds);
18bfb361
DM
5716
5717 my $drive = parse_drive($ds, $conf->{$ds});
5718 next if !$drive;
5719 next if drive_is_cdrom($drive);
5720
5721 my $volid = $drive->{file};
5722
5723 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 5724 $sidhash->{$sid} = $sid if $sid;
18bfb361
DM
5725 }
5726
5727 foreach my $sid (sort keys %$sidhash) {
5728 &$func($sid);
5729 }
5730}
5731
e5eaa028
WL
5732sub do_snapshots_with_qemu {
5733 my ($storecfg, $volid) = @_;
5734
5735 my $storage_name = PVE::Storage::parse_volume_id($volid);
5736
116da784
WL
5737 if ($qemu_snap_storage->{$storecfg->{ids}->{$storage_name}->{type}}
5738 && !$storecfg->{ids}->{$storage_name}->{krbd}){
e5eaa028
WL
5739 return 1;
5740 }
5741
5742 if ($volid =~ m/\.(qcow2|qed)$/){
5743 return 1;
5744 }
5745
5746 return undef;
5747}
5748
4dcc780c
WL
5749sub qga_check_running {
5750 my ($vmid) = @_;
5751
5752 eval { vm_mon_cmd($vmid, "guest-ping", timeout => 3); };
5753 if ($@) {
5754 warn "Qemu Guest Agent are not running - $@";
5755 return 0;
5756 }
5757 return 1;
5758}
5759
04a69bb4
AD
5760sub template_create {
5761 my ($vmid, $conf, $disk) = @_;
5762
04a69bb4 5763 my $storecfg = PVE::Storage::config();
04a69bb4 5764
9cd07842
DM
5765 foreach_drive($conf, sub {
5766 my ($ds, $drive) = @_;
5767
5768 return if drive_is_cdrom($drive);
5769 return if $disk && $ds ne $disk;
5770
5771 my $volid = $drive->{file};
bbd56097 5772 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 5773
04a69bb4
AD
5774 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
5775 $drive->{file} = $voliddst;
152fe752 5776 $conf->{$ds} = print_drive($vmid, $drive);
ffda963f 5777 PVE::QemuConfig->write_config($vmid, $conf);
04a69bb4 5778 });
04a69bb4
AD
5779}
5780
5133de42 5781sub qemu_img_convert {
988e2714 5782 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5133de42
AD
5783
5784 my $storecfg = PVE::Storage::config();
5785 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
5786 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
5787
5788 if ($src_storeid && $dst_storeid) {
6bb91c17
DM
5789
5790 PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
5791
5133de42
AD
5792 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
5793 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
5794
5795 my $src_format = qemu_img_format($src_scfg, $src_volname);
5796 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
5797
5798 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
5799 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
5800
5801 my $cmd = [];
eed24303 5802 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5133de42 5803 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
988e2714
WB
5804 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5805 if ($is_zero_initialized) {
5806 push @$cmd, "zeroinit:$dst_path";
5807 } else {
5808 push @$cmd, $dst_path;
5809 }
5133de42
AD
5810
5811 my $parser = sub {
5812 my $line = shift;
5813 if($line =~ m/\((\S+)\/100\%\)/){
5814 my $percent = $1;
5815 my $transferred = int($size * $percent / 100);
5816 my $remaining = $size - $transferred;
5817
5818 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5819 }
5820
5821 };
5822
5823 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
5824 my $err = $@;
5825 die "copy failed: $err" if $err;
5826 }
5827}
5828
5829sub qemu_img_format {
5830 my ($scfg, $volname) = @_;
5831
d81f0f09 5832 if ($scfg->{path} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5133de42 5833 return $1;
be190583 5834 } else {
5133de42 5835 return "raw";
5133de42
AD
5836 }
5837}
5838
cfad42af 5839sub qemu_drive_mirror {
5a345967 5840 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete) = @_;
cfad42af 5841
5a345967
AD
5842 $jobs = {} if !$jobs;
5843
5844 my $qemu_target;
5845 my $format;
152fe752 5846
5a345967
AD
5847 if($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+)/) {
5848 $qemu_target = $dst_volid;
5849 my $server = $1;
5850 my $port = $2;
5851 $format = "nbd";
5852 die "can't connect remote nbd server $server:$port" if !PVE::Network::tcp_ping($server, $port, 2);
5853 } else {
5854
5855 my $storecfg = PVE::Storage::config();
5856 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid);
5857
5858 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
cfad42af 5859
5a345967 5860 $format = qemu_img_format($dst_scfg, $dst_volname);
21ccdb50 5861
5a345967 5862 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
21ccdb50 5863
5a345967
AD
5864 $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
5865 }
988e2714
WB
5866
5867 my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
88383920
DM
5868 $opts->{format} = $format if $format;
5869
5a345967 5870 print "drive mirror is starting for drive-$drive\n";
21ccdb50 5871
5a345967
AD
5872 eval { vm_mon_cmd($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
5873 if (my $err = $@) {
5874 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
5875 die "mirroring error: $err";
5876 }
5877
5878 $jobs->{"drive-$drive"} = {};
5879
5880 qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $skipcomplete);
5881}
5882
5883sub qemu_drive_mirror_monitor {
5884 my ($vmid, $vmiddst, $jobs, $skipcomplete) = @_;
2e953867 5885
08ac653f 5886 eval {
5a345967
AD
5887
5888 my $err_complete = 0;
5889
08ac653f 5890 while (1) {
5a345967
AD
5891 die "storage migration timed out\n" if $err_complete > 300;
5892
08ac653f 5893 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
08ac653f 5894
5a345967
AD
5895 my $running_mirror_jobs = {};
5896 foreach my $stat (@$stats) {
5897 next if $stat->{type} ne 'mirror';
5898 $running_mirror_jobs->{$stat->{device}} = $stat;
5899 }
08ac653f 5900
5a345967 5901 my $readycounter = 0;
67fb9de6 5902
5a345967
AD
5903 foreach my $job (keys %$jobs) {
5904
5905 if(defined($jobs->{$job}->{complete}) && !defined($running_mirror_jobs->{$job})) {
5906 print "$job : finished\n";
5907 delete $jobs->{$job};
5908 next;
5909 }
5910
5911 die "$job: mirroring has been cancelled. Maybe do you have bad sectors?" if !defined($running_mirror_jobs->{$job});
f34ebd52 5912
5a345967
AD
5913 my $busy = $running_mirror_jobs->{$job}->{busy};
5914 my $ready = $running_mirror_jobs->{$job}->{ready};
5915 if (my $total = $running_mirror_jobs->{$job}->{len}) {
5916 my $transferred = $running_mirror_jobs->{$job}->{offset} || 0;
5917 my $remaining = $total - $transferred;
5918 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
08ac653f 5919
5a345967
AD
5920 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5921 }
f34ebd52 5922
5a345967
AD
5923 $readycounter++ if $running_mirror_jobs->{$job}->{ready} eq 'true';
5924 }
b467f79a 5925
5a345967
AD
5926 last if scalar(keys %$jobs) == 0;
5927
5928 if ($readycounter == scalar(keys %$jobs)) {
5929 print "all mirroring jobs are ready \n";
5930 last if $skipcomplete; #do the complete later
5931
5932 if ($vmiddst && $vmiddst != $vmid) {
5933 # if we clone a disk for a new target vm, we don't switch the disk
5934 PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs);
2e953867 5935 last;
5a345967
AD
5936 } else {
5937
5938 foreach my $job (keys %$jobs) {
5939 # try to switch the disk if source and destination are on the same guest
5940 print "$job : Try to complete block job\n";
5941
5942 eval { vm_mon_cmd($vmid, "block-job-complete", device => $job) };
5943 if ($@ =~ m/cannot be completed/) {
5944 print "$job : block job cannot be complete. Try again \n";
5945 $err_complete++;
5946 }else {
5947 print "$job : complete ok : flushing pending writes\n";
5948 $jobs->{$job}->{complete} = 1;
5949 }
5950 }
2e953867 5951 }
08ac653f 5952 }
08ac653f 5953 sleep 1;
cfad42af 5954 }
08ac653f 5955 };
88383920 5956 my $err = $@;
08ac653f 5957
88383920 5958 if ($err) {
5a345967 5959 eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
88383920
DM
5960 die "mirroring error: $err";
5961 }
5962
5a345967
AD
5963}
5964
5965sub qemu_blockjobs_cancel {
5966 my ($vmid, $jobs) = @_;
5967
5968 foreach my $job (keys %$jobs) {
5969 print "$job: try to cancel block job\n";
5970 eval { vm_mon_cmd($vmid, "block-job-cancel", device => $job); };
5971 $jobs->{$job}->{cancel} = 1;
5972 }
5973
5974 while (1) {
5975 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
5976
5977 my $running_jobs = {};
5978 foreach my $stat (@$stats) {
5979 $running_jobs->{$stat->{device}} = $stat;
5980 }
5981
5982 foreach my $job (keys %$jobs) {
5983
5984 if(defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
5985 print "$job : finished\n";
5986 delete $jobs->{$job};
5987 }
5988 }
5989
5990 last if scalar(keys %$jobs) == 0;
5991
5992 sleep 1;
cfad42af
AD
5993 }
5994}
5995
152fe752 5996sub clone_disk {
be190583 5997 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5a345967 5998 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete) = @_;
152fe752
DM
5999
6000 my $newvolid;
6001
6002 if (!$full) {
6003 print "create linked clone of drive $drivename ($drive->{file})\n";
258e646c 6004 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
152fe752
DM
6005 push @$newvollist, $newvolid;
6006 } else {
5a345967 6007
152fe752
DM
6008 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
6009 $storeid = $storage if $storage;
6010
1377d7b0
DM
6011 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
6012 if (!$format) {
d81f0f09
DM
6013 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
6014 $format = qemu_img_format($scfg, $volname);
152fe752
DM
6015 }
6016
1377d7b0
DM
6017 # test if requested format is supported - else use default
6018 my $supported = grep { $_ eq $format } @$validFormats;
6019 $format = $defFormat if !$supported;
6020
152fe752
DM
6021 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
6022
6023 print "create full clone of drive $drivename ($drive->{file})\n";
6024 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6025 push @$newvollist, $newvolid;
6026
3999f370 6027 PVE::Storage::activate_volumes($storecfg, [$newvolid]);
1dbd6d30 6028
988e2714 6029 my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
152fe752 6030 if (!$running || $snapname) {
988e2714 6031 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit);
152fe752 6032 } else {
2e541679
AD
6033
6034 my $kvmver = get_running_qemu_version ($vmid);
6035 if (!qemu_machine_feature_enabled (undef, $kvmver, 2, 7)) {
961af8a3
WB
6036 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6037 if $drive->{iothread};
2e541679 6038 }
2af848a2 6039
5a345967 6040 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete);
be190583 6041 }
152fe752
DM
6042 }
6043
6044 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
6045
6046 my $disk = $drive;
6047 $disk->{format} = undef;
6048 $disk->{file} = $newvolid;
6049 $disk->{size} = $size;
6050
6051 return $disk;
6052}
6053
ff556cf2
DM
6054# this only works if VM is running
6055sub get_current_qemu_machine {
6056 my ($vmid) = @_;
6057
6058 my $cmd = { execute => 'query-machines', arguments => {} };
8e90138a 6059 my $res = vm_qmp_command($vmid, $cmd);
ff556cf2
DM
6060
6061 my ($current, $default);
6062 foreach my $e (@$res) {
6063 $default = $e->{name} if $e->{'is-default'};
6064 $current = $e->{name} if $e->{'is-current'};
6065 }
6066
6067 # fallback to the default machine if current is not supported by qemu
6068 return $current || $default || 'pc';
6069}
6070
98cfd8b6
AD
6071sub get_running_qemu_version {
6072 my ($vmid) = @_;
6073 my $cmd = { execute => 'query-version', arguments => {} };
6074 my $res = vm_qmp_command($vmid, $cmd);
6075 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6076}
6077
23f73120
AD
6078sub qemu_machine_feature_enabled {
6079 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6080
6081 my $current_major;
6082 my $current_minor;
6083
6084 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6085
6086 $current_major = $3;
6087 $current_minor = $4;
6088
6089 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6090
6091 $current_major = $1;
6092 $current_minor = $2;
6093 }
6094
6095 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6096
6097
6098}
6099
42dbd2ee
AD
6100sub qemu_machine_pxe {
6101 my ($vmid, $conf, $machine) = @_;
6102
6103 $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine;
6104
6105 foreach my $opt (keys %$conf) {
6106 next if $opt !~ m/^net(\d+)$/;
6107 my $net = PVE::QemuServer::parse_net($conf->{$opt});
6108 next if !$net;
6109 my $romfile = PVE::QemuServer::vm_mon_cmd_nocheck($vmid, 'qom-get', path => $opt, property => 'romfile');
6110 return $machine.".pxe" if $romfile =~ m/pxe/;
6111 last;
6112 }
6113
d1363934 6114 return $machine;
42dbd2ee
AD
6115}
6116
249c4a6c
AD
6117sub qemu_use_old_bios_files {
6118 my ($machine_type) = @_;
6119
6120 return if !$machine_type;
6121
6122 my $use_old_bios_files = undef;
6123
6124 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6125 $machine_type = $1;
6126 $use_old_bios_files = 1;
6127 } else {
74cc511f 6128 my $kvmver = kvm_user_version();
249c4a6c
AD
6129 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6130 # load new efi bios files on migration. So this hack is required to allow
6131 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6132 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
74cc511f 6133 $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
249c4a6c
AD
6134 }
6135
6136 return ($use_old_bios_files, $machine_type);
6137}
6138
4543ecf0
AD
6139sub lspci {
6140
6141 my $devices = {};
6142
6143 dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6144 my (undef, $id, $function) = @_;
6145 my $res = { id => $id, function => $function};
6146 push @{$devices->{$id}}, $res;
6147 });
6148
6149 return $devices;
6150}
6151
22de899a
AD
6152sub vm_iothreads_list {
6153 my ($vmid) = @_;
6154
6155 my $res = vm_mon_cmd($vmid, 'query-iothreads');
6156
6157 my $iothreads = {};
6158 foreach my $iothread (@$res) {
6159 $iothreads->{ $iothread->{id} } = $iothread->{"thread-id"};
6160 }
6161
6162 return $iothreads;
6163}
6164
ee034f5c
AD
6165sub scsihw_infos {
6166 my ($conf, $drive) = @_;
6167
6168 my $maxdev = 0;
6169
6170 if ($conf->{scsihw} && ($conf->{scsihw} =~ m/^lsi/)) {
6171 $maxdev = 7;
a1511b3c 6172 } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
ee034f5c
AD
6173 $maxdev = 1;
6174 } else {
6175 $maxdev = 256;
6176 }
6177
6178 my $controller = int($drive->{index} / $maxdev);
a1511b3c 6179 my $controller_prefix = ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') ? "virtioscsi" : "scsihw";
ee034f5c
AD
6180
6181 return ($maxdev, $controller, $controller_prefix);
6182}
a1511b3c 6183
4317f69f
AD
6184sub add_hyperv_enlighments {
6185 my ($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $bios, $gpu_passthrough) = @_;
6186
6187 return if $nokvm;
6188 return if $winversion < 6;
6189 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6190
5aba3953
AD
6191 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6192
4317f69f
AD
6193 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
6194 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6195 push @$cpuFlags , 'hv_vapic';
6196 push @$cpuFlags , 'hv_time';
6197 } else {
6198 push @$cpuFlags , 'hv_spinlocks=0xffff';
6199 }
6200
6201 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 6)) {
6202 push @$cpuFlags , 'hv_reset';
6203 push @$cpuFlags , 'hv_vpindex';
6204 push @$cpuFlags , 'hv_runtime';
6205 }
6206
6207 if ($winversion >= 7) {
6208 push @$cpuFlags , 'hv_relaxed';
4317f69f
AD
6209 }
6210}
6211
6212sub windows_version {
6213 my ($ostype) = @_;
6214
6215 return 0 if !$ostype;
6216
6217 my $winversion = 0;
6218
6219 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6220 $winversion = 5;
6221 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6222 $winversion = 6;
6223 } elsif ($ostype =~ m/^win(\d+)$/) {
6224 $winversion = $1;
6225 }
6226
6227 return $winversion;
6228}
6229
65e866e5
DM
6230# bash completion helper
6231
6232sub complete_backup_archives {
6233 my ($cmdname, $pname, $cvalue) = @_;
6234
6235 my $cfg = PVE::Storage::config();
6236
6237 my $storeid;
6238
6239 if ($cvalue =~ m/^([^:]+):/) {
6240 $storeid = $1;
6241 }
6242
6243 my $data = PVE::Storage::template_list($cfg, $storeid, 'backup');
6244
6245 my $res = [];
6246 foreach my $id (keys %$data) {
6247 foreach my $item (@{$data->{$id}}) {
6248 next if $item->{format} !~ m/^vma\.(gz|lzo)$/;
6249 push @$res, $item->{volid} if defined($item->{volid});
6250 }
6251 }
6252
6253 return $res;
6254}
6255
6256my $complete_vmid_full = sub {
6257 my ($running) = @_;
6258
6259 my $idlist = vmstatus();
6260
6261 my $res = [];
6262
6263 foreach my $id (keys %$idlist) {
6264 my $d = $idlist->{$id};
6265 if (defined($running)) {
6266 next if $d->{template};
6267 next if $running && $d->{status} ne 'running';
6268 next if !$running && $d->{status} eq 'running';
6269 }
6270 push @$res, $id;
6271
6272 }
6273 return $res;
6274};
6275
6276sub complete_vmid {
6277 return &$complete_vmid_full();
6278}
6279
6280sub complete_vmid_stopped {
6281 return &$complete_vmid_full(0);
6282}
6283
6284sub complete_vmid_running {
6285 return &$complete_vmid_full(1);
6286}
6287
335af808
DM
6288sub complete_storage {
6289
6290 my $cfg = PVE::Storage::config();
6291 my $ids = $cfg->{ids};
6292
6293 my $res = [];
6294 foreach my $sid (keys %$ids) {
6295 next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1);
c4c844ef 6296 next if !$ids->{$sid}->{content}->{images};
335af808
DM
6297 push @$res, $sid;
6298 }
6299
6300 return $res;
6301}
6302
1e3baf05 63031;