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