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