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