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